diff --git a/code/nel/include/nel/3d/bloom_effect.h b/code/nel/include/nel/3d/bloom_effect.h index c10967254..49c959e23 100644 --- a/code/nel/include/nel/3d/bloom_effect.h +++ b/code/nel/include/nel/3d/bloom_effect.h @@ -31,6 +31,7 @@ namespace NL3D class UDriver; class UScene; +class CTextureUser; //----------------------------------------------------------------------------------------------------------- //---------------------------------------- CBloomEffect ----------------------------------------------------- @@ -52,19 +53,14 @@ public: // Destructor ~CBloomEffect(); - // Called after the Driver initialization to indicate if OpenGL or Direct3D is used. - // They are some differences in bloom algorithm depending on this API choice. - // If bloom effect is activated and supported, private method init() is called to initialize - // textures and materials. - // initBloomEffect = false => directx - // initBloomEffect = true => opengl - void init(bool initBloomEffect); + // Called after the Driver initialization. + void init(); // must be called before init void setDriver(UDriver *driver) { _Driver = driver; } UDriver* getDriver() const { return _Driver; } - // must be called before initBloom + // must be called before applyBloom void setScene(UScene *scene) { _Scene = scene; } UScene* getScene() const { return _Scene; } @@ -76,6 +72,9 @@ public: void setDensityBloom(uint8 densityBloom) { _DensityBloom = densityBloom; } uint8 getDensityBloom() const { return _DensityBloom; } + // Applies bloom to the current render target + void applyBloom(); + // Called at the beginning of renderAll method in the main loop, if window has been resized, // reinitialize bloom textures according to new window size. // The bloom texture (_InitText attribute) which is used as render target during scene render @@ -83,11 +82,11 @@ public: // If window size exceeds 256*256 the textures used to apply blur are reinitialized with // 256*256 size. If a dimension is less than 256, the texture is initialized with the nearer // power of 2, lower than this window dimension. - void initBloom(); + // void initBloom(); // Called at the end of renderAll method in the main loop, recover stretched texture, apply // both blur passes, and the blending operation between initial render target and the blured one. - void endBloom(); + // void endBloom(); // In OpenGL, the use of FBO implies that Z buffer values of scene render have been stored in // a depth render target. Then, to display 3D interfaces, we must display them in the same FBO, @@ -95,15 +94,12 @@ public: // This method is called at the end of interfaces display in the main loop, to display final render target // (with added interfaces) in the color frame buffer. // NB : In Direct3D, the final render target is displayed at the end of endBloom call. - void endInterfacesDisplayBloom(); + // void endInterfacesDisplayBloom(); private: - // Initialize textures and materials. - void init(); - // Initialize a bloom texture with new dimensions. - void initTexture(NLMISC::CSmartPtr & tex, bool isMode2D, uint32 width, uint32 height); + // void initTexture(NLMISC::CSmartPtr & tex, bool isMode2D, uint32 width, uint32 height); // Called in endBloom method to build a blurred texture. Two passes (then two calls) // are necessary : horizontal and vertical. @@ -130,6 +126,7 @@ private: // density of bloom uint8 _DensityBloom; +/* // render target textures // used to display scene NLMISC::CSmartPtr _InitText; @@ -140,13 +137,12 @@ private: NLMISC::CSmartPtr _BlurHorizontalTex; // original render target NLMISC::CSmartPtr _OriginalRenderTarget; +*/ // materials // used to display first texture in doBlur passes. NL3D::UMaterial _BlurMat; - // used to display final render target texture in endInterfacesDisplayBloom call (OpenGL). - NL3D::UMaterial _DisplayInitMat; // used to blend initial scene render target texture and blur texture according to a // dest+src - dest*src blend operation. NL3D::UMaterial _DisplayBlurMat; @@ -156,21 +152,24 @@ private: // quads NLMISC::CQuadUV _BlurQuad; - NLMISC::CQuadUV _DisplayQuad; - - // openGL or Direct3D? - bool _InitBloomEffect; // textures and materials already initialized? bool _Init; // current window dimensions - uint32 _WndWidth; - uint32 _WndHeight; + /*uint32 _WndWidth; + uint32 _WndHeight;*/ + // Temporary variables used during applyBloom(...) -> // current blur texture dimensions uint32 _BlurWidth; uint32 _BlurHeight; + // used as stretched texture from _InitText, as displayed texture in first blur pass, + // and as render target in second blur pass. + CTextureUser *_BlurFinalTex; + // used as render target in first blur pass, and as displayed texture on second blur pass. + CTextureUser *_BlurHorizontalTex; + // <- }; } // NL3D diff --git a/code/nel/include/nel/3d/driver.h b/code/nel/include/nel/3d/driver.h index 022246838..8738a7dda 100644 --- a/code/nel/include/nel/3d/driver.h +++ b/code/nel/include/nel/3d/driver.h @@ -42,9 +42,6 @@ namespace NLMISC { class IEventEmitter; -struct IMouseDevice; -struct IKeyboardDevice; -struct IInputDeviceManager; class CRect; class CLog; } @@ -75,6 +72,7 @@ struct IOcclusionQuery; /// A Graphic Mode descriptor. struct GfxMode { + std::string DisplayDevice; bool OffScreen; bool Windowed; uint16 Width; @@ -93,7 +91,7 @@ struct GfxMode Frequency = 0; AntiAlias = -1; } - GfxMode(uint16 w, uint16 h, uint8 d, bool windowed = true, bool offscreen = false, uint frequency = 0, sint8 aa = -1); + GfxMode(uint16 w, uint16 h, uint8 d, bool windowed = true, bool offscreen = false, uint frequency = 0, sint8 aa = -1, const std::string &displayDevice = std::string()); }; // **************************************************************************** @@ -259,7 +257,7 @@ public: virtual emptyProc getWindowProc() = 0; virtual NLMISC::IEventEmitter *getEventEmitter() = 0; - + /// Copy a string to system clipboard. virtual bool copyTextToClipboard(const ucstring &text) = 0; @@ -362,7 +360,7 @@ public: virtual void getDepthRange(float &znear, float &zfar) const = 0; // @} - + /// \name Textures // @{ @@ -434,7 +432,7 @@ public: * Under OpenGL this simply returns the maximum number of texture stages (getNbTextureStages) in both return values. */ virtual void getNumPerStageConstant(uint &lightedMaterial, uint &unlightedMaterial) const = 0; - + // [DEPRECATED] Return if this texture is a rectangle texture that requires RECT sampler (OpenGL specific pre-NPOT functionality) virtual bool isTextureRectangle(ITexture *tex) const = 0; @@ -442,7 +440,7 @@ public: virtual bool supportNonPowerOfTwoTextures() const = 0; // @} - + /// \name Texture operations // @{ @@ -536,7 +534,7 @@ public: virtual bool isForceNormalize() const = 0; // @} - + /// \name Vertex Buffer Hard: Features // @{ @@ -737,7 +735,7 @@ public: virtual uint getSwapVBLInterval() = 0; // @} - + @@ -869,29 +867,6 @@ public: /// x and y must be between 0.0 and 1.0 virtual void setMousePos(float x, float y) = 0; - /** Enable / disable low level mouse. This allow to take advantage of some options (speed of the mouse, automatic wrapping) - * It returns a interface to these parameters when it is supported, or NULL otherwise - * The interface pointer is valid as long as the low level mouse is enabled. - * A call to disable the mouse returns NULL, and restore the default mouse behavior - * NB : - In this mode the mouse cursor isn't drawn. - * - Calls to showCursor have no effects - * - Calls to setCapture have no effects - */ - virtual NLMISC::IMouseDevice *enableLowLevelMouse(bool enable, bool exclusive) = 0; - - /** Enable / disable a low level keyboard. - * Such a keyboard can only send KeyDown and KeyUp event. It just consider the keyboard as a - * gamepad with lots of buttons... - * This returns a interface to some parameters when it is supported, or NULL otherwise. - * The interface pointer is valid as long as the low level keyboard is enabled. - * A call to disable the keyboard returns NULL, and restore the default keyboard behavior - */ - virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable) = 0; - - /** Get the delay in ms for mouse double clicks. - */ - virtual uint getDoubleClickDelay(bool hardwareMouse) = 0; - /** If true, capture the mouse to force it to stay under the window. * NB : this has no effects if a low level mouse is used */ @@ -908,11 +883,6 @@ public: // Change default scale for all cursors virtual void setCursorScale(float scale) = 0; - - /** Check whether there is a low level device manager available, and get its interface. Return NULL if not available - * From this interface you can deal with mouse and keyboard as above, but you can also manage game device (joysticks, joypads ...) - */ - virtual NLMISC::IInputDeviceManager *getLowLevelInputDeviceManager() = 0; // @} @@ -1005,6 +975,9 @@ public: ) = 0; // @} + /// Hack for bloom + virtual bool textureCoordinateAlternativeMode() const = 0; + /// \name Render state: Polygon mode @@ -1106,7 +1079,7 @@ public: virtual bool supportVertexProgram(CVertexProgram::TProfile profile) const = 0; /** Compile the given vertex program, return if successful. - * If a vertex program was set active before compilation, + * If a vertex program was set active before compilation, * the state of the active vertex program is undefined behaviour afterwards. */ virtual bool compileVertexProgram(CVertexProgram *program) = 0; @@ -1133,7 +1106,7 @@ public: virtual bool supportPixelProgram(CPixelProgram::TProfile profile) const = 0; /** Compile the given pixel program, return if successful. - * If a pixel program was set active before compilation, + * If a pixel program was set active before compilation, * the state of the active pixel program is undefined behaviour afterwards. */ virtual bool compilePixelProgram(CPixelProgram *program) = 0; @@ -1160,7 +1133,7 @@ public: virtual bool supportGeometryProgram(CGeometryProgram::TProfile profile) const = 0; /** Compile the given pixel program, return if successful. - * If a pixel program was set active before compilation, + * If a pixel program was set active before compilation, * the state of the active pixel program is undefined behaviour afterwards. */ virtual bool compileGeometryProgram(CGeometryProgram *program) = 0; diff --git a/code/nel/include/nel/3d/driver_user.h b/code/nel/include/nel/3d/driver_user.h index ff9ba8973..f1e1fad84 100644 --- a/code/nel/include/nel/3d/driver_user.h +++ b/code/nel/include/nel/3d/driver_user.h @@ -34,7 +34,7 @@ #include "nel/3d/vertex_stream_manager.h" #include "nel/3d/async_texture_manager.h" #include "nel/3d/lod_character_manager.h" - +#include "nel/3d/render_target_manager.h" namespace NL3D { @@ -71,6 +71,7 @@ protected: bool _WindowInit; CMatrixContext _CurrentMatrixContext; CFontManager _FontManager; + CRenderTargetManager _RenderTargetManager; // Components List. typedef CPtrSet TTextureSet; typedef CPtrSet TTextContextSet; @@ -108,6 +109,11 @@ protected: CMaterial _MatTextInternal; CMaterial _MatTextStretchInternal; + // Default render target for effect pipeline + CTextureUser *_EffectRenderTarget; + UMaterial _MatRenderTarget; + CMaterial _MatRenderTargetInt; + NLMISC::CQuadUV _RenderTargetQuad; // StaticInit static bool _StaticInit; @@ -241,6 +247,16 @@ public: // @} + /// Get the render target manager + virtual CRenderTargetManager &getRenderTargetManager() { return _RenderTargetManager; } + + /// Set a texture the size of the window as render target + virtual void beginDefaultRenderTarget(uint32 width = 0, uint32 height = 0); + + /// Draw the render target to the back buffer + virtual void endDefaultRenderTarget(UScene *scene); + + /// \name Components gestion for Interface 2D/3D. // @{ @@ -410,21 +426,6 @@ public: virtual bool fillBuffer (CBitmap &bitmap); // @} - - /// \name Mouse / Keyboards / Game devices - // @{ - virtual NLMISC::IMouseDevice *enableLowLevelMouse(bool enable, bool exclusive); - // - virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable); - virtual NLMISC::IInputDeviceManager *getLowLevelInputDeviceManager(); - - /** - * wrapper for IEventEmitter::emulateMouseRawMode() - */ - virtual void emulateMouseRawMode(bool enable); - - virtual uint getDoubleClickDelay(bool hardwareMouse); - /// show cursor if b is true, or hide it if b is false virtual void showCursor (bool b); /// x and y must be between 0.0 and 1.0 diff --git a/code/nel/include/nel/3d/fxaa.h b/code/nel/include/nel/3d/fxaa.h new file mode 100644 index 000000000..f7ccf4866 --- /dev/null +++ b/code/nel/include/nel/3d/fxaa.h @@ -0,0 +1,84 @@ +/** + * \file fxaa.h + * \brief CFXAA + * \date 2014-08-03 21:41GMT + * \author Jan Boon (Kaetemi) + * CFXAA + */ + +/* + * Copyright (C) 2014 by authors + * + * This file is part of NL3D. + * NL3D is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * NL3D is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with NL3D. If not, see + * . + */ + +#ifndef NL3D_FXAA_H +#define NL3D_FXAA_H +#include + +// STL includes + +// NeL includes +#include +#include + +// Project includes +#include +#include + +#define NL_STEREO_MAX_USER_CAMERAS 8 + +namespace NL3D { + +class ITexture; +class CTextureUser; +class CPixelProgram; +class CVertexProgram; + +/** + * \brief CFXAA + * \date 2014-08-03 21:41GMT + * \author Jan Boon (Kaetemi) + * CFXAA + */ +class CFXAA +{ +public: + CFXAA(NL3D::UDriver *driver); + virtual ~CFXAA(); + + /// Apply effect to current render target. Render target must be managed by render target manager + virtual void applyEffect(); + +private: + UDriver *m_Driver; + + NL3D::UMaterial m_Mat; + // NL3D::CVertexBuffer m_VB; + NLMISC::CQuadUV m_QuadUV; + CVertexProgram *m_VP; + CPixelProgram *m_PP; + + uint m_Width; + uint m_Height; + +}; /* class CFXAA */ + +} /* namespace NL3D */ + +#endif /* #ifndef NL3D_FXAA_H */ + +/* end of file */ diff --git a/code/nel/include/nel/3d/render_target_manager.h b/code/nel/include/nel/3d/render_target_manager.h new file mode 100644 index 000000000..cae8e31b0 --- /dev/null +++ b/code/nel/include/nel/3d/render_target_manager.h @@ -0,0 +1,83 @@ +/** + * \file render_target_manager.h + * \brief CRenderTargetManager + * \date 2014-07-30 21:30GMT + * \author Jan Boon (Kaetemi) + * CRenderTargetManager + */ + +/* + * Copyright (C) 2013 by authors + * + * This file is part of NL3D. + * NL3D is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * NL3D is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with NL3D. If not, see + * . + */ + +#ifndef NL3D_RENDER_TARGET_MANAGER_H +#define NL3D_RENDER_TARGET_MANAGER_H +#include + +// STL includes + +// NeL includes +#include +#include + +// Project includes +#include + +namespace NL3D { + +class UDriver; +class ITexture; +class CTextureUser; +class CDriverUser; + +struct CRenderTargetDescInt; + +/** + * \brief CRenderTargetManager + * \date 2013-07-03 20:17GMT + * \author Jan Boon (Kaetemi) + * CRenderTargetManager + * Usage: Call 'getRenderTarget' when you start using a render target, + * call 'recycledRenderTarget' when the render target can be recycled. + * At end of frame call cleanup. + * Assumes semi-constant render target quantity between frames, + * except on changes of resolution or feature settings. + */ +class CRenderTargetManager +{ +public: + CRenderTargetManager(); + ~CRenderTargetManager(); + + NL3D::CTextureUser *getRenderTarget(uint width, uint height, bool mode2D = false, UTexture::TUploadFormat format = UTexture::Auto); + void recycleRenderTarget(NL3D::CTextureUser *renderTarget); + + void cleanup(); + +private: + friend class CDriverUser; + NL3D::UDriver *m_Driver; + std::vector m_RenderTargets; + +}; /* class CRenderTargetManager */ + +} /* namespace NL3D */ + +#endif /* #ifndef NL3D_RENDER_TARGET_MANAGER_H */ + +/* end of file */ diff --git a/code/nel/include/nel/3d/render_trav.h b/code/nel/include/nel/3d/render_trav.h index d50d2c242..6e41d8282 100644 --- a/code/nel/include/nel/3d/render_trav.h +++ b/code/nel/include/nel/3d/render_trav.h @@ -139,7 +139,7 @@ public: * \param renderPart : The part of the scene that must be rendered * \param newRender true If scene render is beginning. Otherwise other parts of the scene have already been rendered. */ - void traverse(UScene::TRenderPart renderPart, bool newRender); + void traverse(UScene::TRenderPart renderPart, bool newRender, bool generateShadows); //@} /// \name RenderList. diff --git a/code/nel/include/nel/3d/scene.h b/code/nel/include/nel/3d/scene.h index 50dfe6b8a..12c18b484 100644 --- a/code/nel/include/nel/3d/scene.h +++ b/code/nel/include/nel/3d/scene.h @@ -157,7 +157,7 @@ public: * \param doHrcPass set it to false to indicate that the CHrcTrav have not to be traversed. Useful to optimize if * you know that NONE of your models have moved (a good example is a shoot of the scene from different cameras). */ - void render(bool doHrcPass=true); + void render(bool doHrcPass = true); /** Begin Part Rendering * During beginPartRender()/endPartRender(), you can ask other scene to render their part, but you should @@ -171,10 +171,10 @@ public: * WARNING: always must begin rendering with at least UScene::RenderOpaque, else shadows won't work * WARNING: assert-crash if a part in 'rp' has already been rendered since the last beginPartRender() */ - void renderPart(UScene::TRenderPart rp, bool doHrcPass=true); + void renderPart(UScene::TRenderPart rp, bool doHrcPass = true, bool doTrav = true, bool keepTrav = false); /** End Part Rendering (commit model creation and deletion that were asked during rendering) */ - void endPartRender(); + void endPartRender(bool keepTrav = false); //@} diff --git a/code/nel/include/nel/3d/scene_user.h b/code/nel/include/nel/3d/scene_user.h index 708c8bfd7..639fa33d8 100644 --- a/code/nel/include/nel/3d/scene_user.h +++ b/code/nel/include/nel/3d/scene_user.h @@ -96,8 +96,8 @@ public: // render methods virtual void render(bool updateWaitingInstances = true, bool restoreMatrixContextAfterRender = true); virtual void beginPartRender(); - virtual void renderPart(TRenderPart rp); - virtual void endPartRender(bool updateWaitingInstances = true, bool restoreMatrixContextAfterRender = true); + virtual void renderPart(TRenderPart rp, bool doHrcPass = true, bool doTrav = true, bool keepTrav = false); + virtual void endPartRender(bool updateWaitingInstances = true, bool restoreMatrixContextAfterRender = true, bool keepTrav = true); // update async loading whithout a call to render virtual void updateWaitingInstances(double ellapsedTime); diff --git a/code/nel/include/nel/3d/stereo_debugger.h b/code/nel/include/nel/3d/stereo_debugger.h index b07a9630c..6c974f93d 100644 --- a/code/nel/include/nel/3d/stereo_debugger.h +++ b/code/nel/include/nel/3d/stereo_debugger.h @@ -65,10 +65,17 @@ public: /// Sets driver and generates necessary render targets virtual void setDriver(NL3D::UDriver *driver); - void releaseTextures(); + /*void releaseTextures(); void initTextures(); void setTextures(); - void verifyTextures(); + void verifyTextures();*/ + void getTextures(); + void recycleTextures(); + + /// Attach the driver to the display + virtual bool attachToDisplay(); + /// Detach the driver from the display + virtual void detachFromDisplay(); /// Gets the required screen resolution for this device virtual bool getScreenResolution(uint &width, uint &height); @@ -76,6 +83,8 @@ public: virtual void updateCamera(uint cid, const NL3D::UCamera *camera); /// Get the frustum to use for clipping virtual void getClippingFrustum(uint cid, NL3D::UCamera *camera) const; + /// Get the original frustum of the camera + virtual void getOriginalFrustum(uint cid, NL3D::UCamera *camera) const; /// Is there a next pass virtual bool nextPass(); @@ -89,14 +98,21 @@ public: virtual void getCurrentMatrix(uint cid, NL3D::UCamera *camera) const; /// At the start of a new render target - virtual bool wantClear(); + virtual bool wantClear(); /// The 3D scene virtual bool wantScene(); + /// Scene post processing effects + virtual bool wantSceneEffects(); /// Interface within the 3D scene virtual bool wantInterface3D(); /// 2D Interface virtual bool wantInterface2D(); + /// Is this the first 3D scene of the frame + virtual bool isSceneFirst(); + /// Is this the last 3D scene of the frame + virtual bool isSceneLast(); + /// Returns true if a new render target was set, always fase if not using render targets virtual bool beginRenderTarget(); /// Returns true if a render target was fully drawn, always false if not using render targets @@ -116,9 +132,7 @@ private: CFrustum m_Frustum[NL_STEREO_MAX_USER_CAMERAS]; CMatrix m_CameraMatrix[NL_STEREO_MAX_USER_CAMERAS]; - NLMISC::CSmartPtr m_LeftTex; NL3D::CTextureUser *m_LeftTexU; - NLMISC::CSmartPtr m_RightTex; NL3D::CTextureUser *m_RightTexU; NL3D::UMaterial m_Mat; NLMISC::CQuadUV m_QuadUV; diff --git a/code/nel/include/nel/3d/stereo_display.h b/code/nel/include/nel/3d/stereo_display.h index 3b9c73b74..3b6fdbb21 100644 --- a/code/nel/include/nel/3d/stereo_display.h +++ b/code/nel/include/nel/3d/stereo_display.h @@ -94,6 +94,11 @@ public: /// Sets driver and generates necessary render targets virtual void setDriver(NL3D::UDriver *driver) = 0; + + /// Attach the driver to the display, return true if attached + virtual bool attachToDisplay() = 0; + /// Detach the driver from the display + virtual void detachFromDisplay() = 0; /// Gets the required screen resolution for this device virtual bool getScreenResolution(uint &width, uint &height) = 0; @@ -101,6 +106,8 @@ public: virtual void updateCamera(uint cid, const NL3D::UCamera *camera) = 0; /// Get the frustum to use for clipping virtual void getClippingFrustum(uint cid, NL3D::UCamera *camera) const = 0; + /// Get the original frustum of the camera + virtual void getOriginalFrustum(uint cid, NL3D::UCamera *camera) const = 0; /// Is there a next pass virtual bool nextPass() = 0; @@ -114,20 +121,28 @@ public: virtual void getCurrentMatrix(uint cid, NL3D::UCamera *camera) const = 0; /// At the start of a new render target - virtual bool wantClear() = 0; + virtual bool wantClear() = 0; /// The 3D scene virtual bool wantScene() = 0; + /// Scene post processing effects + virtual bool wantSceneEffects() = 0; /// Interface within the 3D scene virtual bool wantInterface3D() = 0; /// 2D Interface virtual bool wantInterface2D() = 0; + /// Is this the first 3D scene of the frame + virtual bool isSceneFirst() = 0; + /// Is this the last 3D scene of the frame + virtual bool isSceneLast() = 0; + /// Returns true if a new render target was set, always fase if not using render targets virtual bool beginRenderTarget() = 0; /// Returns true if a render target was fully drawn, always false if not using render targets virtual bool endRenderTarget() = 0; static const char *getLibraryName(CStereoDeviceInfo::TStereoDeviceLibrary library); + // List all devices. Device creation factories are no longer valid after re-calling this function static void listDevices(std::vector &devicesOut); static IStereoDisplay *createDevice(const CStereoDeviceInfo &deviceInfo); static void releaseUnusedLibraries(); diff --git a/code/nel/include/nel/3d/stereo_hmd.h b/code/nel/include/nel/3d/stereo_hmd.h index 95c159cfd..3276e78fe 100644 --- a/code/nel/include/nel/3d/stereo_hmd.h +++ b/code/nel/include/nel/3d/stereo_hmd.h @@ -53,6 +53,9 @@ public: /// Get the HMD orientation virtual NLMISC::CQuat getOrientation() const = 0; + /// Set the GUI reference + virtual void setInterfaceMatrix(const NL3D::CMatrix &matrix) = 0; + /// Get GUI center (1 = width, 1 = height, 0 = center) virtual void getInterface2DShift(uint cid, float &x, float &y, float distance) const = 0; diff --git a/code/nel/include/nel/3d/stereo_ovr.h b/code/nel/include/nel/3d/stereo_ovr.h index ba6895bf0..750f32027 100644 --- a/code/nel/include/nel/3d/stereo_ovr.h +++ b/code/nel/include/nel/3d/stereo_ovr.h @@ -44,7 +44,7 @@ #ifndef NL3D_STEREO_OVR_H #define NL3D_STEREO_OVR_H -#ifdef HAVE_LIBOVR +#ifdef HAVE_LIBOVR_02 #include @@ -91,6 +91,8 @@ public: virtual void updateCamera(uint cid, const NL3D::UCamera *camera); /// Get the frustum to use for clipping virtual void getClippingFrustum(uint cid, NL3D::UCamera *camera) const; + /// Get the original frustum of the camera + virtual void getOriginalFrustum(uint cid, NL3D::UCamera *camera) const; /// Is there a next pass virtual bool nextPass(); @@ -121,6 +123,9 @@ public: /// Get the HMD orientation virtual NLMISC::CQuat getOrientation() const; + /// Set the GUI reference + virtual void setInterfaceMatrix(const NL3D::CMatrix &matrix); + /// Get GUI center (1 = width, 1 = height, 0 = center) virtual void getInterface2DShift(uint cid, float &x, float &y, float distance) const; @@ -132,33 +137,37 @@ public: /// Set the scale of the game in units per meter virtual void setScale(float s); + /// Calculates internal camera information based on the reference camera + void initCamera(uint cid, const NL3D::UCamera *camera); + /// Render GUI + void renderGUI(); + + /// Checks if the device used by this class was actually created + bool isDeviceCreated(); static void listDevices(std::vector &devicesOut); static bool isLibraryInUse(); static void releaseLibrary(); - - /// Calculates internal camera information based on the reference camera - void initCamera(uint cid, const NL3D::UCamera *camera); - /// Checks if the device used by this class was actually created - bool isDeviceCreated(); - private: CStereoOVRDevicePtr *m_DevicePtr; int m_Stage; int m_SubStage; + CViewport m_RegularViewport; CViewport m_LeftViewport; CViewport m_RightViewport; CFrustum m_ClippingFrustum[NL_STEREO_MAX_USER_CAMERAS]; CFrustum m_LeftFrustum[NL_STEREO_MAX_USER_CAMERAS]; CFrustum m_RightFrustum[NL_STEREO_MAX_USER_CAMERAS]; + CFrustum m_OriginalFrustum[NL_STEREO_MAX_USER_CAMERAS]; CMatrix m_CameraMatrix[NL_STEREO_MAX_USER_CAMERAS]; + CMatrix m_InterfaceCameraMatrix; mutable bool m_OrientationCached; mutable NLMISC::CQuat m_OrientationCache; UDriver *m_Driver; - NLMISC::CSmartPtr m_BarrelTex; - NL3D::CTextureUser *m_BarrelTexU; + NL3D::CTextureUser *m_SceneTexture; NL3D::UMaterial m_BarrelMat; + NL3D::CTextureUser *m_GUITexture; NLMISC::CQuadUV m_BarrelQuadLeft; NLMISC::CQuadUV m_BarrelQuadRight; NLMISC::CRefPtr m_PixelProgram; diff --git a/code/nel/include/nel/3d/stereo_ovr_04.h b/code/nel/include/nel/3d/stereo_ovr_04.h new file mode 100644 index 000000000..8bda88c88 --- /dev/null +++ b/code/nel/include/nel/3d/stereo_ovr_04.h @@ -0,0 +1,225 @@ +/** + * \file stereo_ovr.h + * \brief CStereoOVR + * \date 2014-08-04 16:21GMT + * \author Jan Boon (Kaetemi) + * CStereoOVR + */ + +/* + * Copyright (C) 2014 by authors + * + * This file is part of NL3D. + * NL3D is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * NL3D is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with NL3D. If not, see + * . + * + * Linking this library statically or dynamically with other modules + * is making a combined work based on this library. Thus, the terms + * and conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with the Oculus SDK to produce + * an executable, regardless of the license terms of the Oculus SDK, + * and distribute linked combinations including the two, provided that + * you also meet the terms and conditions of the license of the Oculus + * SDK. You must obey the GNU General Public License in all respects + * for all of the code used other than the Oculus SDK. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. + */ + +#ifndef NL3D_STEREO_OVR_04_H +#define NL3D_STEREO_OVR_04_H + +#ifdef HAVE_LIBOVR + +#include + +// STL includes + +// NeL includes +#include +#include + +// Project includes +#include +#include +#include +#include +#include +#include +#include + +struct ovrHmdDesc_; +typedef const ovrHmdDesc_ *ovrHmd; + +namespace NL3D { + +class ITexture; +class CTextureUser; +class CStereoOVRDeviceFactory; + +#define NL_STEREO_MAX_USER_CAMERAS 8 +#define NL_OVR_EYE_COUNT 2 + +/** + * \brief CStereoOVR + * \date 2014-08-04 16:21GMT + * \author Jan Boon (Kaetemi) + * CStereoOVR + */ +class CStereoOVR : public IStereoHMD +{ +public: + CStereoOVR(const CStereoOVRDeviceFactory *factory); + virtual ~CStereoOVR(); + + /// Sets driver and generates necessary render targets + virtual void setDriver(NL3D::UDriver *driver); + + /// Attach the driver to the display + virtual bool attachToDisplay(); + /// Detach the driver from the display + virtual void detachFromDisplay(); + + /// Gets the required screen resolution for this device + virtual bool getScreenResolution(uint &width, uint &height); + /// Set latest camera position etcetera + virtual void updateCamera(uint cid, const NL3D::UCamera *camera); + /// Get the frustum to use for clipping + virtual void getClippingFrustum(uint cid, NL3D::UCamera *camera) const; + /// Get the original frustum of the camera + virtual void getOriginalFrustum(uint cid, NL3D::UCamera *camera) const; + + /// Is there a next pass + virtual bool nextPass(); + /// Gets the current viewport + virtual const NL3D::CViewport &getCurrentViewport() const; + /// Gets the current camera frustum + virtual const NL3D::CFrustum &getCurrentFrustum(uint cid) const; + /// Gets the current camera frustum + virtual void getCurrentFrustum(uint cid, NL3D::UCamera *camera) const; + /// Gets the current camera matrix + virtual void getCurrentMatrix(uint cid, NL3D::UCamera *camera) const; + + /// At the start of a new render target + virtual bool wantClear(); + /// The 3D scene + virtual bool wantScene(); + /// Scene post processing effects + virtual bool wantSceneEffects(); + /// Interface within the 3D scene + virtual bool wantInterface3D(); + /// 2D Interface + virtual bool wantInterface2D(); + + /// Is this the first 3D scene of the frame + virtual bool isSceneFirst(); + /// Is this the last 3D scene of the frame + virtual bool isSceneLast(); + + /// Returns true if a new render target was set, always fase if not using render targets + virtual bool beginRenderTarget(); + /// Returns true if a render target was fully drawn, always false if not using render targets + virtual bool endRenderTarget(); + + + /// Get the HMD orientation + virtual NLMISC::CQuat getOrientation() const; + + /// Set the GUI reference + virtual void setInterfaceMatrix(const NL3D::CMatrix &matrix); + + /// Get GUI center (1 = width, 1 = height, 0 = center) + virtual void getInterface2DShift(uint cid, float &x, float &y, float distance) const; + + /// Set the head model, eye position relative to orientation point + virtual void setEyePosition(const NLMISC::CVector &v); + /// Get the head model, eye position relative to orientation point + virtual const NLMISC::CVector &getEyePosition() const; + + /// Set the scale of the game in units per meter + virtual void setScale(float s); + + /// Calculates internal camera information based on the reference camera + void initCamera(uint cid, const NL3D::UCamera *camera); + /// Render GUI + void renderGUI(); + + /// Checks if the device used by this class was actually created + bool isDeviceCreated(); + + static void listDevices(std::vector &devicesOut); + static bool isLibraryInUse(); + static void releaseLibrary(); + +private: + ovrHmd m_DevicePtr; + bool m_DebugDevice; + + int m_Stage; + int m_SubStage; + + CViewport m_RegularViewport; + CViewport m_EyeViewport[NL_OVR_EYE_COUNT]; + CFrustum m_EyeFrustumBase[NL_OVR_EYE_COUNT]; + uint m_RenderTargetWidth; + uint m_RenderTargetHeight; + NLMISC::CVector2f m_EyeUVScaleOffset[NL_OVR_EYE_COUNT][2]; + float m_EyeViewAdjustX[NL_OVR_EYE_COUNT]; + + CVertexBuffer m_VB[NL_OVR_EYE_COUNT]; + CIndexBuffer m_IB[NL_OVR_EYE_COUNT]; + uint32 m_NbTris[NL_OVR_EYE_COUNT]; + + CFrustum m_ClippingFrustum[NL_STEREO_MAX_USER_CAMERAS]; + CFrustum m_LeftFrustum[NL_STEREO_MAX_USER_CAMERAS]; + CFrustum m_RightFrustum[NL_STEREO_MAX_USER_CAMERAS]; + CFrustum m_OriginalFrustum[NL_STEREO_MAX_USER_CAMERAS]; + CMatrix m_CameraMatrix[NL_STEREO_MAX_USER_CAMERAS]; + CMatrix m_InterfaceCameraMatrix; + mutable bool m_OrientationCached; + mutable NLMISC::CQuat m_OrientationCache; + + UDriver *m_Driver; + + CTextureUser *m_GUITexture; + NL3D::CTextureUser *m_SceneTexture; + + UMaterial m_UnlitMat; + + UDriver::CMode m_OriginalMode; + sint32 m_OriginalWinPosX; + sint32 m_OriginalWinPosY; + bool m_AttachedDisplay; + + /* + NL3D::UMaterial m_BarrelMat; + NLMISC::CQuadUV m_BarrelQuadLeft; + NLMISC::CQuadUV m_BarrelQuadRight; + NLMISC::CRefPtr m_PixelProgram;*/ + NLMISC::CVector m_EyePosition; + float m_Scale; + +}; /* class CStereoOVR */ + +} /* namespace NL3D */ + +#endif /* HAVE_LIBOVR */ + +#endif /* #ifndef NL3D_STEREO_OVR_04_H */ + +/* end of file */ diff --git a/code/nel/include/nel/3d/u_driver.h b/code/nel/include/nel/3d/u_driver.h index 67e0c30fd..dc2b02e56 100644 --- a/code/nel/include/nel/3d/u_driver.h +++ b/code/nel/include/nel/3d/u_driver.h @@ -35,9 +35,6 @@ namespace NLMISC { - struct IMouseDevice; - struct IKeyboardDevice; - struct IInputDeviceManager; class CLog; } @@ -63,6 +60,7 @@ class U3dMouseListener; class ULight; class UAnimationSet; class UWaterEnvMap; +class CRenderTargetManager; typedef void (*emptyProc)(void); @@ -94,6 +92,7 @@ public: /// A Graphic Mode descriptor. struct CMode { + std::string DisplayDevice; bool Windowed; uint16 Width; uint16 Height; @@ -110,8 +109,9 @@ public: Frequency = 0; AntiAlias = -1; } - CMode(uint16 w, uint16 h, uint8 d, bool windowed= true, uint frequency = 0, sint8 aa = -1) + CMode(uint16 w, uint16 h, uint8 d, bool windowed= true, uint frequency = 0, sint8 aa = -1, const std::string &displayDevice = std::string()) { + DisplayDevice = displayDevice; Windowed = windowed; Width = w; Height = h; @@ -309,6 +309,16 @@ public: // @} + /// Get the render target manager + virtual CRenderTargetManager &getRenderTargetManager() =0; + + /// Set a texture of specified size or of the size of the window as render target + virtual void beginDefaultRenderTarget(uint32 width = 0, uint32 height = 0) =0; + + /// Draw the render target to the back buffer + virtual void endDefaultRenderTarget(UScene *scene) =0; + + /// \name Components gestion for Interface 2D/3D. // @{ @@ -556,36 +566,6 @@ public: /// \name Mouse / Keyboard / Gamedevices // @{ - /** Enable / disable low level mouse. This allow to take advantage of some options (speed of the mouse, automatic wrapping) - * It returns a interface to these parameters when it is supported, or NULL otherwise - * The interface pointer is valid as long as the low level mouse is enabled. - * A call to disable the mouse returns NULL, and restore the default mouse behaviour - * NB : - In this mode the mouse cursor isn't drawn. - * - Calls to showCursor have no effects - * - Calls to setCapture have no effects - */ - virtual NLMISC::IMouseDevice *enableLowLevelMouse(bool enable, bool hardware) = 0; - - /** Enable / disable a low level keyboard. - * This returns a interface to some parameters when it is supported, or NULL otherwise. - * The interface pointer is valid as long as the low level keyboard is enabled. - * A call to disable the keyboard returns NULL, and restore the default keyboard behaviour. - */ - virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable) = 0; - - /** Check whether there is a low level device manager available, and get its interface. Return NULL if not available. - * From this interface you can deal with mouse and keyboard as above, but you can also manage game devices (joysticks, joypads ...) - */ - virtual NLMISC::IInputDeviceManager *getLowLevelInputDeviceManager() = 0; - - /** - * wrapper for IEventEmitter::emulateMouseRawMode() - */ - virtual void emulateMouseRawMode(bool enable) = 0; - - // get delay used for mouse double click - virtual uint getDoubleClickDelay(bool hardwareMouse) = 0; - /** show cursor if b is true, or hide it if b is false * NB: This has no effects if a low level mouse is used. */ diff --git a/code/nel/include/nel/3d/u_scene.h b/code/nel/include/nel/3d/u_scene.h index d60266afe..c0733c5d2 100644 --- a/code/nel/include/nel/3d/u_scene.h +++ b/code/nel/include/nel/3d/u_scene.h @@ -134,14 +134,17 @@ public: /** Render a part (see render() for what it does) * beginPartRender() must have been called * \param renderPart a combination of UScene::TRenderPart flags, allow to choose which part of the scene must be rendered + * \param doHrcPass set it to false to indicate that the CHrcTrav have not to be traversed. Useful to optimize if + * you know that NONE of your models have moved (a good example is a shoot of the scene from different cameras). + * \param doTrav set to false when processing a second frame for stereo rending to avoid unnecessary traversals. * WARNING: always must begin rendering with at least UScene::RenderOpaque, else shadows won't work * WARNING: assert-crash if a part in 'rp' has already been rendered since the last beginPartRender() */ - virtual void renderPart(UScene::TRenderPart rp) =0; + virtual void renderPart(UScene::TRenderPart rp, bool doHrcPass = true, bool doTrav = true, bool keepTrav = false) =0; /** End Part Rendering (commit model creation and deletion that were asked during rendering) */ - virtual void endPartRender(bool updateWaitingInstances = true, bool restoreMatrixContextAfterRender = true) =0; + virtual void endPartRender(bool updateWaitingInstances = true, bool restoreMatrixContextAfterRender = true, bool keepTrav = false) =0; /** Update waiting instances and igs that are loaded asynchronously diff --git a/code/nel/include/nel/misc/di_event_emitter.h b/code/nel/include/nel/misc/di_event_emitter.h deleted file mode 100644 index 41c7bbf47..000000000 --- a/code/nel/include/nel/misc/di_event_emitter.h +++ /dev/null @@ -1,204 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_DI_EVENT_EMITTER_H -#define NL_DI_EVENT_EMITTER_H - - - -#include "types_nl.h" - - -#ifdef NL_OS_WINDOWS - - -#define DIRECTINPUT_VERSION 0x0800 - -#include "input_device_server.h" -#include "input_device_manager.h" -#include "event_emitter.h" -#include "smart_ptr.h" -#include "events.h" -#include "rect.h" -#include "game_device.h" -#ifndef NL_COMP_MINGW -# define NOMINMAX -#endif -#include -#include - - - -namespace NLMISC -{ - - -class CWinEventEmitter; -class CDIKeyboard; -class CDIMouse; -struct IMouseDevice; -struct IKeyboardDevice; - -// -struct EDirectInput : public EInputDevice -{ - EDirectInput(const char *reason) : EInputDevice(reason) {} -}; -// -struct EDirectInputLibNotFound : public EDirectInput -{ - EDirectInputLibNotFound() : EDirectInput("can't found the direct input dll") {} -}; -// -struct EDirectInputInitFailed : public EDirectInput -{ - EDirectInputInitFailed() : EDirectInput("Direct input initialization failed") {} -}; -// -struct EDirectInputCooperativeLevelFailed : public EDirectInput -{ - EDirectInputCooperativeLevelFailed() : EDirectInput("Direct Input Device Cooperative level couldn't be set") {} -}; - - -// Class to represent Direct Inputs events -struct CDIEvent : public IInputDeviceEvent -{ - virtual bool operator < (const IInputDeviceEvent &ide) const - { - // just compare the dates - return Datas.dwTimeStamp < (safe_cast(&ide))->Datas.dwTimeStamp; - } - DIDEVICEOBJECTDATA Datas; -}; - -/** - * This manage events by using DirectInput8. - * This should be polled regularly. - * This can be mixed with a CWinEmitter (for example, you may have mouse using direct input, and keyboard using standard messages) - * \author Nicolas Vizerie - * \author Nevrax France - * \date 2002 - */ -class CDIEventEmitter : public IEventEmitter, public IInputDeviceManager -{ -public: - /** Build a Direct Input Event Emitter object. An exception containing the reason is thrown if the initialization failed. - * The obtained object must be released by deleting it. - * \param hinst the instance of the application. - * \param hwnd the main window of the application. - * \param we A windows eventsemitter. Can be NULL. Needed if you want to mix WIN32 events and Direct Input events - * (for example, a Direct Input Mouse and a Win32 Keyboard) - */ - static CDIEventEmitter *create(HINSTANCE hinst, HWND hwnd, CWinEventEmitter *we) throw(EDirectInput); - ~CDIEventEmitter(); -public: - - /// This poll the direct input state, directly storing the result in the given server, or keeping the result in internal server if NULL. - void poll(CEventServer *server = NULL); - - ///\name From IDeviceManager, access to devices - //@{ - // Test if a mouse has been created (by a call to getMouseDeivce) - virtual bool isMouseCreated() { return _Mouse != NULL; } - /** Create the mouse device if needed (one active at a time for that object, repeated calls returns the same pointer) and get an interface on it. An exception if thrown if it couldn't be obtained. - * If this object has a pointer on a win32 emiter, Win32 mouse messages are replaced by this mouse messages. - */ - virtual IMouseDevice *getMouseDevice(bool hardware) throw(EInputDevice); - /// remove the direct input mouse - virtual void releaseMouse(); - /** Create the keyboard device if needed (one active at a time for that object, repeated calls returns the same pointer) and get an interface on it. - * If this object has a pointer on a win32 emiter, Win32 keyboard messages are replaced by this keyboard messages. - * NB: A direct input has no notion of localization or key combinations. See keyboard_device.h for more infos - */ - virtual IKeyboardDevice *getKeyboardDevice() throw(EInputDevice); - /// remove the direct input keyboard - virtual void releaseKeyboard(); - // Enumerates current game devices (gamepads, joystick etc.). The result is stored in the given vector - virtual void enumerateGameDevice(TDeviceDescVect &descs) throw(EInputDevice); - // Create the given game device from its instance name. It also means that it will begin to sends inputs - virtual IGameDevice *createGameDevice(const std::string &instanceName) throw(EInputDevice); - // Release the given game device - virtual void releaseGameDevice(IGameDevice *); - //@} - - /// from IEventEmitter - virtual void submitEvents(CEventServer &server, bool allWindows); - virtual void emulateMouseRawMode(bool enable); - - // Build a TMouseButton value from the current buttons state - TMouseButton buildButtonsFlags() const; - // Build a TMouseButton value (but with no mouse values) - TMouseButton buildKeyboardButtonFlags() const - { - return (TMouseButton) (buildButtonsFlags() & (ctrlButton|shiftButton|altButton)); - } - -//================================================================ -//================================================================ -//================================================================ -private: - typedef HRESULT (WINAPI * TPDirectInput8Create) (HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID* ppvOut, LPUNKNOWN punkOuter); - // Private internal server message, used to stored all messages internally before to dispatch them, when no server is supplied to poll(... - class CDIEventServer : CEventServer - { - friend class CDIEventEmitter; - public: - void setServer (CEventServer *server) - { - _Server = server; - } - private: - bool pumpEvent(CEvent *event) - { - CEventServer::pumpEvent(event); - _Server->postEvent (event); - return false; - } - private: - CEventServer *_Server; - }; -private: - HWND _hWnd; - TMouseButton _ButtonsFlags; - NLMISC::CRefPtr _WE; - static HMODULE _DirectInputLibHandle; - static TPDirectInput8Create _PDirectInput8Create; - static uint _NumCreatedInterfaces; -private: - static bool loadLib(); - static void unloadLib(); -//==== -private: - CDIEventServer _InternalServer; - CInputDeviceServer _DeviceServer; - IDirectInput8 *_DInput8; - CDIMouse *_Mouse; - CDIKeyboard *_Keyboard; -private: - CDIEventEmitter(HWND hwnd, CWinEventEmitter *we); -}; - - - -} // NLMISC - -#endif // NL_WINDOWS - - -#endif // NL_DX_EVENT_EMITTER_H - -/* End of dx_event_emitter.h */ diff --git a/code/nel/include/nel/misc/event_emitter.h b/code/nel/include/nel/misc/event_emitter.h index 224e5159f..eab005b82 100644 --- a/code/nel/include/nel/misc/event_emitter.h +++ b/code/nel/include/nel/misc/event_emitter.h @@ -49,19 +49,6 @@ public: * \param server */ virtual void submitEvents(CEventServer & server, bool allWindows) = 0; - - /** - * Instruct the event emitter to send CGDMouseMove instead of CEventMouseMove. - * - * On windows, the mouse device can be set into RawMode. Using this mode, - * CGDMouseMove events (only containing the raw movement delta) are emitted - * instead of the normal CEventMouseMove events (containing the mouse position). - * - * On Linux and Mac OS X, there is no MouseDevice implementation, all the - * events are created by the event emitter. So the event emitter has to - * emulate the mouse raw mode. - */ - virtual void emulateMouseRawMode(bool) = 0; }; diff --git a/code/nel/include/nel/misc/event_emitter_multi.h b/code/nel/include/nel/misc/event_emitter_multi.h index 3c6860e53..e41ee2055 100644 --- a/code/nel/include/nel/misc/event_emitter_multi.h +++ b/code/nel/include/nel/misc/event_emitter_multi.h @@ -47,7 +47,6 @@ public: const IEventEmitter *getEmitter(uint index) const; /// From IEventEmitter. This call submitEvents on all the emitters virtual void submitEvents(CEventServer &server, bool allWindows); - virtual void emulateMouseRawMode(bool enable); virtual bool copyTextToClipboard(const ucstring &text); virtual bool pasteTextFromClipboard(ucstring &text); diff --git a/code/nel/include/nel/misc/game_device.h b/code/nel/include/nel/misc/game_device.h deleted file mode 100644 index 605c4fb53..000000000 --- a/code/nel/include/nel/misc/game_device.h +++ /dev/null @@ -1,114 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_GAME_DEVICE_H -#define NL_GAME_DEVICE_H - -#include "types_nl.h" -#include "input_device.h" -#include -#include - - -namespace NLMISC -{ - -/// Describe a game device -struct CGameDeviceDesc -{ - // type of the device - enum TDevType { GamePad, Joystick, DontKnow, DevTypeLast } DevType; - // Friendly name for the instance. For example, "Joystick 1." - std::string InstanceName; - // Friendly name for the product - std::string ProductName; - // Tells whether this device is connected - bool Connected; -}; - -// a list of game device description -typedef std::vector TDeviceDescVect; - -/// for devices comparison. The 'Connected' field is ignored. -inline bool operator == (const CGameDeviceDesc &lhs, const CGameDeviceDesc &rhs) -{ - return lhs.InstanceName == rhs.InstanceName && lhs.ProductName == rhs.ProductName; -} -// -inline bool operator != (const CGameDeviceDesc &lhs, const CGameDeviceDesc &rhs) -{ - return !(lhs == rhs); -} - - -/** - * This abstract a joystick or gamepad - * \author Nicolas Vizerie - * \author Nevrax France - * \date 2002 - */ -struct IGameDevice : public IInputDevice -{ - enum TAxis { XAxis = 0, YAxis, ZAxis, /* translation */ - RXAxis, RYAxis, RZAxis, /* rotations */ - MaxNumAxis - }; - - /// Get a general description of this device - virtual const CGameDeviceDesc &getDescription() const = 0; - - ///\name Controls presence - //@{ - // returns the number of buttons available on this game device - virtual uint getNumButtons() const = 0; - /** Check if the given axe is present on this game device - * NB : only absolute axis are managed - */ - virtual bool hasAxis(TAxis axis) const = 0; - // Check the number of sliders presents on this game device - virtual uint getNumSliders() const = 0; - // Check the number of point of views controls present on this game device - virtual uint getNumPOV() const = 0; - //@} - - ///\name Controls names. Must ensure that controls are present before calling these methods. - //@{ - virtual const char *getButtonName(uint index) const = 0; - virtual const char *getAxisName(TAxis axis) const = 0; - virtual const char *getSliderName(uint index) const = 0; - virtual const char *getPOVName(uint index) const = 0; - //@} - - ///\name Controls state. Must ensure that controls are present before calling these methods. - //@{ - // Return true if the given button is pushed. - virtual bool getButtonState(uint index) const = 0; - // Return a value in [-1, 1] for a translation axis, or an orientation. - virtual float getAxisValue(TAxis axis) const = 0; - // Return a value in [0, 1] - virtual float getSliderPos(uint index) const = 0; - // Return a CCW angle in degrees - virtual float getPOVAngle(uint index) const = 0; - //@} -}; - - -} // NLMISC - - -#endif // NL_GAME_DEVICE_H - -/* End of GAME_device.h */ diff --git a/code/nel/include/nel/misc/game_device_events.h b/code/nel/include/nel/misc/game_device_events.h deleted file mode 100644 index 6ddee4589..000000000 --- a/code/nel/include/nel/misc/game_device_events.h +++ /dev/null @@ -1,209 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_GAME_DEVICE_EVENT_H -#define NL_GAME_DEVICE_EVENT_H - -#include "types_nl.h" -#include "events.h" -#include "game_device.h" - - - - -namespace NLMISC -{ - -struct IMouseDevice; -struct IGameDevice; - -const CClassId EventGDMouseMove(0x12142bc4, 0x43c73e74); -const CClassId EventGDButtonDownId(0x57141957, 0x3efb143a); -const CClassId EventGDButtonUpId(0x16105e06, 0x302536b2); -const CClassId EventGDAxisMovedId(0x073306, 0x41173626); -const CClassId EventGDSliderMovedId(0x68776586, 0x394a6916); -const CClassId EventGDPOVChanged(0x362851b9, 0x395c4d61); - - -//========================================================================================== -/// A raw mouse move message, expressed in mickeys (relative values) -class CGDMouseMove : public CEvent -{ -public: - IMouseDevice *MD; - sint X, Y; -public: - CGDMouseMove(IEventEmitter *emitter, IMouseDevice *md, sint x, sint y) : CEvent(emitter, EventGDMouseMove), MD(md), X(x), Y(y) - {} - - virtual CEvent *clone() const {return new CGDMouseMove(*this);} -}; - - -//========================================================================================== -/** - * An event from a game device (joystick, joypad ...) - */ -class CGameDeviceEvent : public CEvent -{ -public: - /// the game device this event come from - IGameDevice *GameDevice; -public: - CGameDeviceEvent( - IGameDevice *gameDevice, - IEventEmitter *emitter, - const CClassId &classId - ) - : CEvent(emitter, classId), - GameDevice(gameDevice) - {} -}; - - -//========================================================================================== -/** A button state has changed - */ -class CGDButton : public CGameDeviceEvent -{ -public: - // index of the buttons that has been pushed - uint ButtonIndex; - bool Pushed; -public: - /// - CGDButton( - uint buttonIndex, - bool pushed, - IGameDevice *gameDevice, - IEventEmitter *emitter, - const CClassId &classId - ) - : CGameDeviceEvent(gameDevice, emitter, classId), - ButtonIndex(buttonIndex), - Pushed(pushed) - {} -}; - - -//========================================================================================== -/** A button has been pushed - */ -class CGDButtonDown : public CGDButton -{ -public: - /// - CGDButtonDown(uint buttonIndex, IGameDevice *gameDevice, IEventEmitter *emitter) - : CGDButton(buttonIndex, true, gameDevice, emitter, EventGDButtonDownId) - {} - - virtual CEvent *clone() const {return new CGDButtonDown(*this);} -}; - -//========================================================================================== -/** A button has been released - */ -class CGDButtonUp : public CGDButton -{ -public: - /// - CGDButtonUp(uint buttonIndex, IGameDevice *gameDevice, IEventEmitter *emitter) - : CGDButton(buttonIndex, false, gameDevice, emitter, EventGDButtonUpId) - {} - - virtual CEvent *clone() const {return new CGDButtonUp(*this);} -}; - -//========================================================================================== -/// An axis has moved -class CGDAxisMoved : public CGameDeviceEvent -{ -public: - IGameDevice::TAxis Axis; - // current position of the axis, ranges from -1.f to 1.f - float Value; -public: - CGDAxisMoved( - IGameDevice::TAxis axis, - float value, - IGameDevice *gameDevice, - IEventEmitter *emitter - ) - : CGameDeviceEvent(gameDevice, emitter, EventGDAxisMovedId), - Axis(axis), - Value(value) - {} - - virtual CEvent *clone() const {return new CGDAxisMoved(*this);} -}; - - -//========================================================================================== -/// A slider position has changed -class CGDSliderMoved : public CGameDeviceEvent -{ -public: - uint SliderIndex; - // current position of the slider, ranges from 0.f to 1.f - float SliderPos; -public: - CGDSliderMoved( - float sliderPos, - uint sliderIndex, - IGameDevice *gameDevice, - IEventEmitter *emitter - ) - : CGameDeviceEvent(gameDevice, emitter, EventGDSliderMovedId), - SliderIndex(sliderIndex), - SliderPos(sliderPos) - {} - - virtual CEvent *clone() const {return new CGDSliderMoved(*this);} -}; - -//========================================================================================== -/// A point of view control changed -class CGDPOVChanged : public CGameDeviceEvent -{ -public: - uint POVIndex; - bool Centered; - // The POV angle, in degrees (CW) - float POVAngle; -public: - CGDPOVChanged( - bool centered, - float povAngle, - uint povIndex, - IGameDevice *gameDevice, - IEventEmitter *emitter - ) - : CGameDeviceEvent(gameDevice, emitter, EventGDPOVChanged), - POVIndex(povIndex), - Centered(centered), - POVAngle(povAngle) - {} - - virtual CEvent *clone() const {return new CGDPOVChanged(*this);} -}; - - -} // NLMISC - - -#endif // NL_GAME_DEVICE_EVENT_H - -/* End of game_device_event.h */ diff --git a/code/nel/include/nel/misc/input_device.h b/code/nel/include/nel/misc/input_device.h deleted file mode 100644 index b07a0128e..000000000 --- a/code/nel/include/nel/misc/input_device.h +++ /dev/null @@ -1,84 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_INPUT_DEVICE_H -#define NL_INPUT_DEVICE_H - -#include "types_nl.h" - - -namespace NLMISC -{ - - -class CEventServer; -class CInputDeviceServer; -struct IInputDeviceEvent; - - -/** - * Base class that wrap to a device - * \author Nicolas Vizerie - * \author Nevrax France - * \date 2002 - */ - -struct IInputDevice -{ - /** Set the buffer size for this device (the number of samples it can retains). - * This return true if the size could be set - */ - virtual bool setBufferSize(uint size) = 0; - /// Get the buffer size for this device - virtual uint getBufferSize() const = 0; - - ///\name Device server specifics. You usually don't want to call these - //@{ - /** For device server usage : - * Called at the beginning of each events retrieval. - * If a device doesn't support buffered datas, the state changes can be directly send to the event server. - * The default does nothing. - */ - virtual void begin(CEventServer * /* server */) {} - - /** For device server usage : - * Poll all events from that device, and notify them to the given device server, so that they can be sorted between devices. - * This retrieves messages, but do not process them. - */ - virtual void poll(CInputDeviceServer *dev) = 0; - /** For device server usage : - * Process an event (eventually update this device state), and translate the message to a IEventServerMessage - */ - virtual void submit(IInputDeviceEvent *deviceEvent, CEventServer *server) = 0; - /** For device server usage : - * Says that the next message is for another device, or that it is the last message that will be received. - * This allow to pack several messages in one (for example, to sum up mouse moves until a click occurs) - * The default does nothing. - * The next message can be used to get a time stamp for example. It may be NULL is no next message is available - */ - virtual void transitionOccured(CEventServer * /* server */, const IInputDeviceEvent * /* nextMessage */) {} - //@} - - // dtor - virtual ~IInputDevice() {} -}; - -} // NLMISC - - -#endif // NL_INPUT_DEVICE_H - -/* End of input_device.h */ diff --git a/code/nel/include/nel/misc/input_device_manager.h b/code/nel/include/nel/misc/input_device_manager.h deleted file mode 100644 index a23437696..000000000 --- a/code/nel/include/nel/misc/input_device_manager.h +++ /dev/null @@ -1,69 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_INPUT_DEVICE_MANAGER_H -#define NL_INPUT_DEVICE_MANAGER_H - -#include "types_nl.h" -#include "game_device.h" -#include "common.h" - -namespace NLMISC -{ - - -struct IMouseDevice; -struct IKeyboardDevice; - - - -struct EInputDevice : public Exception -{ - EInputDevice(const char *reason) : Exception(reason) {} -}; - - -/** Interface for objects that give low level access to devices (mouse, keyboard, joypads and joysticks). - * Generally an object implementing this interface will send the appropriate events when a device is 'created'. - * (Example of implementation : a direct input event emitter) - */ -struct IInputDeviceManager -{ - // Test if a mouse has been created (by a call to getMouseDeivce) - virtual bool isMouseCreated() = 0; - /// Create the low level mouse device if needed (one active at a time for that object, repeated calls returns the same pointer). An exception if thrown if it couldn't be obtained. - virtual IMouseDevice *getMouseDevice(bool hardware) throw(EInputDevice) = 0; - /// remove the low level mouse - virtual void releaseMouse() = 0; - /// Create the low level keyboard device if needed (one active at a time for that object, repeated calls returns the same pointer). An exception if thrown if it couldn't be obtained. - virtual IKeyboardDevice *getKeyboardDevice() throw(EInputDevice) = 0; - /// remove the low level keyboard - virtual void releaseKeyboard() = 0; - // Enumerates current game devices (gamepads, joystick etc.). The result is stored in the given vector - virtual void enumerateGameDevice(TDeviceDescVect &descs) throw(EInputDevice) = 0; - // Create the given game device interface from its instance name. It also means that it will begin to sends events. - virtual IGameDevice *createGameDevice(const std::string &instanceName) throw(EInputDevice) = 0; - // Release the given game device. - virtual void releaseGameDevice(IGameDevice *gd) = 0; -}; - - -} // NLMISC - - -#endif // NL_INPUT_DEVICE_MANAGER_H - -/* End of device_manager.h */ diff --git a/code/nel/include/nel/misc/input_device_server.h b/code/nel/include/nel/misc/input_device_server.h deleted file mode 100644 index 45c3db77d..000000000 --- a/code/nel/include/nel/misc/input_device_server.h +++ /dev/null @@ -1,84 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_INPUT_DEVICE_SERVER_H -#define NL_INPUT_DEVICE_SERVER_H - -#include "types_nl.h" -#include - - -namespace NLMISC -{ - -class CEventServer; -struct IInputDevice; -struct IInputDeviceEvent; - - -/** Base class for an input device server. Unlike an event server, it manages several devices, and can sort their events (by date for example). - * It keeps a list of active devices. - * It can poll datas from every active device. - * It can sort devices messages to submit them in correct order to a CEventServer. - */ - -class CInputDeviceServer -{ -public: - /// register a device into this device server. - void registerDevice(IInputDevice *device); - /// remove a device from this server (but does not delete it). - void removeDevice(IInputDevice *device); - // returns the number of registered devices - uint getNumDevices() const { return (uint)_Devices.size(); } - // return a device - IInputDevice *getDevice(uint index) { return _Devices[index]; } - /// Test whether the given device is handled by this server. - bool isDevice(IInputDevice *device) const; - /// Retrieve datas from the devices, and submit them to the given CEventServer. - void poll(CEventServer *server); - /// Allow an input device to register an event. The event will then be deleted by this server - void submitEvent(IInputDeviceEvent *deviceEvent); - // dtor - virtual ~CInputDeviceServer() {} -private: - typedef std::vector TDeviceCont; - typedef std::vector TEventCont; -private: - TDeviceCont _Devices; - TEventCont _Events; -}; - - - - -/** An event from an input device. - */ -struct IInputDeviceEvent -{ - IInputDevice *Emitter; // the input device that emitted that event - // Used to sort events by time stamp. - virtual bool operator < (const IInputDeviceEvent &IInputDeviceEvent) const = 0; - virtual ~IInputDeviceEvent() {} -}; - - -} // NLMISC - - -#endif // NL_INPUT_DEVICE_SERVER_H - -/* End of input_device_server.h */ diff --git a/code/nel/include/nel/misc/keyboard_device.h b/code/nel/include/nel/misc/keyboard_device.h deleted file mode 100644 index bf3b2af8d..000000000 --- a/code/nel/include/nel/misc/keyboard_device.h +++ /dev/null @@ -1,63 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_KEYBOARD_DEVICE_H -#define NL_KEYBOARD_DEVICE_H - -#include "types_nl.h" -#include "events.h" -#include "input_device.h" - - - -namespace NLMISC -{ - -/** Gives access to low level keyboard parameters - * - 'Shift' messages are replaced by RShift and LShift msg. - * - 'Control' messages are replaced by 'RControl' and 'LControl' msg. - * - 'Menu' (alternate) messages are replaced by 'RMenu' and 'LMenu' msg. - */ -struct IKeyboardDevice : public IInputDevice -{ - /// Max number of supported keys - enum { NumKeys = 256 }; - /// Get the delay before key repeat, in milliseconds - virtual uint getKeyRepeatDelay() const = 0; - /// Get the delay before key repeat, in milliseconds - virtual void setKeyRepeatDelay(uint delay) = 0; - /// Get the period before key repeat, in milliseconds - virtual uint getKeyRepeatPeriod() const = 0; - /// Get the period before key repeat, in milliseconds - virtual void setKeyRepeatPeriod(uint period) = 0; - /// Set a set of keys for which repetition is disabled - virtual void disableRepetition(const TKey *keyTab, uint numKey) = 0; - /// Get the number of disabled keys - virtual uint getNumDisabledRepetition() const = 0; - /** Get the disabled keys and stores in the given tab. - * NB: must ensure the destination table has the right size - * \see getNumDisabledKeys() - */ - virtual void getDisabledRepetitions(TKey *destTab) const = 0; -}; - - -} // NLMISC - - -#endif // NL_KEYBOARD_DEVICE_H - -/* End of keyboard_device.h */ diff --git a/code/nel/include/nel/misc/mouse_device.h b/code/nel/include/nel/misc/mouse_device.h deleted file mode 100644 index 8ae181cdd..000000000 --- a/code/nel/include/nel/misc/mouse_device.h +++ /dev/null @@ -1,130 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_MOUSE_DEVICE_H -#define NL_MOUSE_DEVICE_H - -#include "types_nl.h" -#include "input_device.h" - - - -namespace NLMISC -{ - -class CRect; - -/// An interface to a low level mouse device -struct IMouseDevice : public IInputDevice -{ - enum TAxisMode { Raw, Clamped, AxisModeLast }; - enum TAxis { XAxis = 0, YAxis = 1, AxisLast }; - enum TMessageMode { NormalMode, RawMode, MessageModeLast }; - - ///\name Messages - //@{ - /** Tells what messages should be sent : - * DEFAULT is 'raw' messages - * Raw messages : - no clamping nor frames applied - * - no speed applied - * - no factor applied - * - CGDMouseMove messages are sent - * - Move expressed in mickeys - * Normal messages : - CEventMouseMove messages are sent - * - A frame may clamp one or both axis - * - The mouse speed can be changed - */ - virtual void setMessagesMode(TMessageMode mode) = 0; - /// retrieve what kinds of messages are sent - virtual TMessageMode getMessagesMode() const = 0; - //@} - - ///\name Mouse MOVE, valid only - //@{ - /** Set the mode of axis of the mouse. This can be raw, or clamped. In clamped mode, a frame is used to limit the move. - * NB : invalid in raw message mode - * \see setMouseFrame(const CRect &rect) - */ - virtual void setMouseMode(TAxis axis, TAxisMode axisMode) = 0; - /** returns the mode of the mouse for the given axis. - * NB : invalid in raw message mode - */ - virtual TAxisMode getMouseMode(TAxis axis) const = 0; - /** Set the mouse speed. It must be in the ]0, +inf] range, 1 gives the natural mouse speed. - * NB : invalid in raw message mode - */ - virtual void setMouseSpeed(float speed) = 0; - /** Get the mouse speed. - * NB : invalid in raw message mode - */ - virtual float getMouseSpeed() const = 0; - /** Set the mouse acceleration. It is the threshold in mickey, when start the acceleration. 0 means not acceleration. - */ - virtual void setMouseAcceleration(uint speed) = 0; - /** Get the mouse acceleration. - */ - virtual uint getMouseAcceleration() const = 0; - /** Set the current frame in which the mouse can move, expressed in pixels. - * NB do not forget to call setMouseFactors if you want the results to be reported in the 0-1 range. - * NB : invalid in raw message mode. - * \see setMouseFactors - */ - virtual void setMouseFrame(const CRect &rect) = 0; - /** Gives factor by which the mouse coordinates must be multiplied before an event is sent. - * The default factor is 1. - * NB : invalid in raw message mode. - * - * Example : this set a frame of 800x600 and reports event in the [0, 1] range. - * \code - * mouse->setMouseFrame(800, 600); - * mouse->setMouseMode(XAxis, IMouseDevice::Clamped); - * mouse->setMouseMode(YAxis, IMouseDevice::Clamped); - * mouse->setFactors(1.f / 800, 1.f / 600); - * \endcode - */ - virtual void setFactors(float xFactor, float yFactor) = 0; - /** Get the x factor, use to multiply the mouse position before an event is sent. - * NB : invalid in raw message mode. - * \see setFactors() - */ - virtual float getXFactor() const = 0; - /** Get the y factor, use to multiply the mouse position before an event is sent. - * NB : invalid in raw message mode. - * \see setFactors() - */ - virtual float getYFactor() const = 0; - //@} - - // Get the current frame used for limiting mouse movements - virtual const CRect &getMouseFrame() const = 0; - // Set the maximum delay for a double click to be taken in account (in ms). - virtual void setDoubleClickDelay(uint ms) = 0; - // Get the maximum delay for double click (in ms) - virtual uint getDoubleClickDelay() const = 0; - // Force the position of the mouse, expressed in pixels - virtual void setMousePos(float x, float y) = 0; - - /// From a delta of a mouse position input (eg from CEventMouseMove), deduce delta in mickeys (eg: like received from a CGDMouseMove) - virtual void convertStdMouseMoveInMickeys(float &dx, float &dy) const = 0; -}; - - -} // NLMISC - - -#endif // NL_MOUSE_DEVICE_H - -/* End of u_mouse_device.h */ diff --git a/code/nel/include/nel/misc/win_event_emitter.h b/code/nel/include/nel/misc/win_event_emitter.h index 756dfbaee..1b361485f 100644 --- a/code/nel/include/nel/misc/win_event_emitter.h +++ b/code/nel/include/nel/misc/win_event_emitter.h @@ -100,8 +100,6 @@ public: */ bool processMessage (HWND hWnd, uint32 msg, WPARAM wParam, LPARAM lParam, CEventServer *server=NULL); - void emulateMouseRawMode(bool enable); - private: CWinEventServer _InternalServer; HWND _HWnd; diff --git a/code/nel/src/3d/CMakeLists.txt b/code/nel/src/3d/CMakeLists.txt index fff343915..21184eb12 100644 --- a/code/nel/src/3d/CMakeLists.txt +++ b/code/nel/src/3d/CMakeLists.txt @@ -562,8 +562,13 @@ SOURCE_GROUP(Fx\\Particles\\lights FILES ps_light.cpp ../../include/nel/3d/ps_light.h) SOURCE_GROUP(Fx\\2d FILES + render_target_manager.cpp + ../../include/nel/3d/render_target_manager.h bloom_effect.cpp ../../include/nel/3d/bloom_effect.h + fxaa.cpp + fxaa_program.h + ../../include/nel/3d/fxaa.h deform_2d.cpp ../../include/nel/3d/deform_2d.h heat_haze.cpp @@ -700,6 +705,9 @@ SOURCE_GROUP(Stereo FILES stereo_ovr.cpp stereo_ovr_fp.cpp ../../include/nel/3d/stereo_ovr.h + stereo_ovr_04.cpp + stereo_ovr_04_program.h + ../../include/nel/3d/stereo_ovr_04.h stereo_libvr.cpp ../../include/nel/3d/stereo_libvr.h stereo_debugger.cpp diff --git a/code/nel/src/3d/bloom_effect.cpp b/code/nel/src/3d/bloom_effect.cpp index 7809aba2c..c468349ac 100644 --- a/code/nel/src/3d/bloom_effect.cpp +++ b/code/nel/src/3d/bloom_effect.cpp @@ -72,79 +72,47 @@ CBloomEffect::CBloomEffect() _SquareBloom = true; _DensityBloom = 128; _Init = false; - _InitBloomEffect = false; + + _BlurFinalTex = NULL; + _BlurHorizontalTex = NULL; } //----------------------------------------------------------------------------------------------------------- CBloomEffect::~CBloomEffect() { - if(_Init) + if (_Init) { - if(!_DisplayInitMat.empty()) + if (!_DisplayBlurMat.empty()) { - _DisplayInitMat.getObjectPtr()->setTexture(0, NULL); - if (_Driver) _Driver->deleteMaterial(_DisplayInitMat); - } - _InitText = NULL; - - if(!_DisplayBlurMat.empty()) - { - _DisplayBlurMat.getObjectPtr()->setTexture(0, NULL); if (_Driver) _Driver->deleteMaterial(_DisplayBlurMat); } - if(!_DisplaySquareBlurMat.empty()) + + if (!_DisplaySquareBlurMat.empty()) { - _DisplaySquareBlurMat.getObjectPtr()->setTexture(0, NULL); - _DisplaySquareBlurMat.getObjectPtr()->setTexture(1, NULL); if (_Driver) _Driver->deleteMaterial(_DisplaySquareBlurMat); } - if(!_BlurMat.empty()) + if (!_BlurMat.empty()) { - _BlurMat.getObjectPtr()->setTexture(0, NULL); - _BlurMat.getObjectPtr()->setTexture(1, NULL); - _BlurMat.getObjectPtr()->setTexture(2, NULL); - _BlurMat.getObjectPtr()->setTexture(3, NULL); if (_Driver) _Driver->deleteMaterial(_BlurMat); } - - _BlurHorizontalTex = NULL; - _BlurFinalTex = NULL; } } //----------------------------------------------------------------------------------------------------------- -void CBloomEffect::init(bool initBloomEffect) -{ - _InitBloomEffect = initBloomEffect; - - if(((CDriverUser *)_Driver)->getDriver()->supportBloomEffect()) - init(); -} - -//----------------------------------------------------------------------------------------------------------- - void CBloomEffect::init() { - _WndWidth = _Driver->getWindowWidth(); - _WndHeight = _Driver->getWindowHeight(); + if (!((CDriverUser *)_Driver)->getDriver()->supportBloomEffect()) + return; + + CDriverUser *dru = static_cast(_Driver); + IDriver *drv = dru->getDriver(); _BlurWidth = 256; _BlurHeight = 256; - // initialize textures - _InitText = NULL; - _BlurHorizontalTex = NULL; - _BlurFinalTex = NULL; - if(_InitBloomEffect) - { - initTexture(_InitText, false, _WndWidth, _WndHeight); - } - initTexture(_BlurFinalTex, true, _BlurWidth, _BlurHeight); - initTexture(_BlurHorizontalTex, true, _BlurWidth, _BlurHeight); - // initialize blur material _BlurMat = _Driver->createMaterial(); CMaterial * matObject = _BlurMat.getObjectPtr(); @@ -187,22 +155,6 @@ void CBloomEffect::init() matObject->texEnvArg1RGB(3, CMaterial::Constant, CMaterial::SrcColor); matObject->texEnvArg2RGB(3, CMaterial::Previous, CMaterial::SrcColor); - // initialize display materials - if(_InitBloomEffect) - { - _DisplayInitMat = _Driver->createMaterial(); - CMaterial * matObjectInit = _DisplayInitMat.getObjectPtr(); - _DisplayInitMat.initUnlit(); - _DisplayInitMat.setColor(CRGBA::White); - _DisplayInitMat.setBlend (false); - _DisplayInitMat.setAlphaTest (false); - matObjectInit->setBlendFunc (CMaterial::one, CMaterial::zero); - matObjectInit->setZWrite(false); - matObjectInit->setZFunc(CMaterial::always); - matObjectInit->setDoubleSided(true); - matObjectInit->setTexture(0, _InitText); - } - // initialize linear blur material _DisplayBlurMat = _Driver->createMaterial(); CMaterial * matObjectFinal = _DisplayBlurMat.getObjectPtr(); @@ -214,7 +166,7 @@ void CBloomEffect::init() matObjectFinal->setZFunc(CMaterial::always); matObjectFinal->setDoubleSided(true); - matObjectFinal->setTexture(0, _BlurFinalTex); + // matObjectFinal->setTexture(0, _BlurFinalTex); matObjectFinal->texEnvOpRGB(0, CMaterial::Modulate); matObjectFinal->texEnvArg0RGB(0, CMaterial::Texture, CMaterial::SrcColor); matObjectFinal->texEnvArg1RGB(0, CMaterial::Constant, CMaterial::SrcColor); @@ -230,163 +182,93 @@ void CBloomEffect::init() matObjectFinal->setZFunc(CMaterial::always); matObjectFinal->setDoubleSided(true); - matObjectFinal->setTexture(0, _BlurFinalTex); matObjectFinal->texEnvOpRGB(0, CMaterial::Modulate); matObjectFinal->texEnvArg0RGB(0, CMaterial::Texture, CMaterial::SrcColor); matObjectFinal->texEnvArg1RGB(0, CMaterial::Constant, CMaterial::SrcColor); - matObjectFinal->setTexture(1, _BlurFinalTex); matObjectFinal->texEnvOpRGB(1, CMaterial::Modulate); matObjectFinal->texEnvArg0RGB(1, CMaterial::Texture, CMaterial::SrcColor); matObjectFinal->texEnvArg1RGB(1, CMaterial::Previous, CMaterial::SrcColor); // initialize quads - _DisplayQuad.V0 = CVector(0.f, 0.f, 0.5f); - _DisplayQuad.V1 = CVector(1.f, 0.f, 0.5f); - _DisplayQuad.V2 = CVector(1.f, 1.f, 0.5f); - _DisplayQuad.V3 = CVector(0.f, 1.f, 0.5f); - _BlurQuad.V0 = CVector(-1.f, -1.f, 0.5f); _BlurQuad.V1 = CVector(1.f, -1.f, 0.5f); _BlurQuad.V2 = CVector(1.f, 1.f, 0.5f); _BlurQuad.V3 = CVector(-1.f, 1.f, 0.5f); + if (drv->textureCoordinateAlternativeMode()) + { + _BlurQuad.Uv0 = CUV(0.f, 1.f); + _BlurQuad.Uv1 = CUV(1.f, 1.f); + _BlurQuad.Uv2 = CUV(1.f, 0.f); + _BlurQuad.Uv3 = CUV(0.f, 0.f); + } + else + { + _BlurQuad.Uv0 = CUV(0.f, 0.f); + _BlurQuad.Uv1 = CUV(1.f, 0.f); + _BlurQuad.Uv2 = CUV(1.f, 1.f); + _BlurQuad.Uv3 = CUV(0.f, 1.f); + } _Init = true; } //----------------------------------------------------------------------------------------------------------- -void CBloomEffect::initTexture(CSmartPtr & tex, bool isMode2D, uint32 width, uint32 height) +void CBloomEffect::applyBloom() { - NL3D::IDriver *drvInternal = ((CDriverUser *) _Driver)->getDriver(); - - tex = new CTextureBloom(); - tex->setReleasable(false); - tex->resize(width, height); - tex->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff); - tex->setWrapS(ITexture::Clamp); - tex->setWrapT(ITexture::Clamp); - ((CTextureBloom *)tex.getPtr())->mode2D(isMode2D); - if(tex->TextureDrvShare==NULL || tex->TextureDrvShare->DrvTexture.getPtr()==NULL) - { - tex->setRenderTarget(true); - drvInternal->setupTexture(*tex); - } -} - -//----------------------------------------------------------------------------------------------------------- - -void CBloomEffect::initBloom() // clientcfg -{ - if(!((CDriverUser *)_Driver)->getDriver()->supportBloomEffect()) + if (!((CDriverUser *)_Driver)->getDriver()->supportBloomEffect()) return; // don't activate bloom when PolygonMode is different from Filled if (_Driver->getPolygonMode() != UDriver::Filled) return; - if(_Driver->getWindowWidth()==0 || _Driver->getWindowHeight()==0) + if (_Driver->getWindowWidth()==0 || _Driver->getWindowHeight()==0) return; - if(!_Init) + if (!_Init) init(); - _OriginalRenderTarget = static_cast(_Driver)->getDriver()->getRenderTarget(); + CDriverUser *dru = static_cast(_Driver); + IDriver *drv = dru->getDriver(); - // if window resize, reinitialize textures - if(_WndWidth!=_Driver->getWindowWidth() || _WndHeight!=_Driver->getWindowHeight()) - { - _WndWidth = _Driver->getWindowWidth(); - _WndHeight = _Driver->getWindowHeight(); + // backup + bool fogEnabled = _Driver->fogEnabled(); + _Driver->enableFog(false); - if(_InitBloomEffect) - { - // release old SmartPtr - _DisplayInitMat.getObjectPtr()->setTexture(0, NULL); - _InitText = NULL; + NL3D::ITexture *renderTarget = drv->getRenderTarget(); + nlassert(renderTarget); + nlassert(renderTarget->isBloomTexture()); - initTexture(_InitText, false, _WndWidth, _WndHeight); + uint width = renderTarget->getWidth(); + uint height = renderTarget->getHeight(); + bool mode2D = static_cast(renderTarget)->isMode2D(); + nlassert(renderTarget->getUploadFormat() == ITexture::Auto); - _DisplayInitMat.getObjectPtr()->setTexture(0, _InitText); - } + if (width >= 256) _BlurWidth = 256; + else _BlurWidth = raiseToNextPowerOf2(width) / 2; + if (height >= 256) _BlurHeight = 256; + else _BlurHeight = raiseToNextPowerOf2(height) / 2; - bool reinitBlurTextures = false; - if(_WndWidth<_BlurWidth || _WndHeight<_BlurHeight) - { - _BlurWidth = raiseToNextPowerOf2(_WndWidth)/2; - _BlurHeight = raiseToNextPowerOf2(_WndHeight)/2; + nlassert(!_BlurFinalTex); + _BlurFinalTex = _Driver->getRenderTargetManager().getRenderTarget(_BlurWidth, _BlurHeight, true); + nlassert(!_BlurHorizontalTex); + _BlurHorizontalTex = _Driver->getRenderTargetManager().getRenderTarget(_BlurWidth, _BlurHeight, true); - reinitBlurTextures = true; - } + _DisplayBlurMat.getObjectPtr()->setTexture(0, _BlurFinalTex->getITexture()); + _DisplaySquareBlurMat.getObjectPtr()->setTexture(0, _BlurFinalTex->getITexture()); + _DisplaySquareBlurMat.getObjectPtr()->setTexture(1, _BlurFinalTex->getITexture()); - if(_WndWidth>256 && _BlurWidth!=256) - { - _BlurWidth = 256; - reinitBlurTextures = true; - } + CTextureUser texNull; + dru->setRenderTarget(texNull); - if(_WndHeight>256 && _BlurHeight!=256) - { - _BlurHeight = 256; - reinitBlurTextures = true; - } - - if(reinitBlurTextures) - { - // release old SmartPtr - _DisplayBlurMat.getObjectPtr()->setTexture(0, NULL); - - _DisplaySquareBlurMat.getObjectPtr()->setTexture(0, NULL); - _DisplaySquareBlurMat.getObjectPtr()->setTexture(1, NULL); - - _BlurMat.getObjectPtr()->setTexture(0, NULL); - _BlurMat.getObjectPtr()->setTexture(1, NULL); - _BlurMat.getObjectPtr()->setTexture(2, NULL); - _BlurMat.getObjectPtr()->setTexture(3, NULL); - - _BlurHorizontalTex = NULL; - _BlurFinalTex = NULL; - - initTexture(_BlurFinalTex, true, _BlurWidth, _BlurHeight); - initTexture(_BlurHorizontalTex, true, _BlurWidth, _BlurHeight); - - _DisplayBlurMat.getObjectPtr()->setTexture(0, _BlurFinalTex); - - _DisplaySquareBlurMat.getObjectPtr()->setTexture(0, _BlurFinalTex); - _DisplaySquareBlurMat.getObjectPtr()->setTexture(1, _BlurFinalTex); - } - } - - if (!_OriginalRenderTarget) - { - NL3D::CTextureUser txt = (_InitBloomEffect) ? (CTextureUser(_InitText)) : (CTextureUser()); - if(!(static_cast(_Driver)->setRenderTarget(txt, 0, 0, _WndWidth, _WndHeight))) - { - nlwarning("setRenderTarget return false with initial texture for bloom effect\n"); - return; - } - } -} - -//----------------------------------------------------------------------------------------------------------- - -void CBloomEffect::endBloom() // clientcfg -{ - if(!_Driver->supportBloomEffect() || !_Init) - return; - - // don't activate bloom when PolygonMode is different from Filled - if (_Driver->getPolygonMode() != UDriver::Filled) return; - - if(_Driver->getWindowWidth()==0 || _Driver->getWindowHeight()==0) - return; - - CTextureUser txt1 = _OriginalRenderTarget ? CTextureUser(_OriginalRenderTarget) : ((_InitBloomEffect) ? (CTextureUser(_InitText)) : (CTextureUser())); - CTextureUser txt2(_BlurFinalTex); - CRect rect1(0, 0, _WndWidth, _WndHeight); + // Stretch original render target into blur texture + CTextureUser txt1(renderTarget); + CTextureUser txt2(_BlurFinalTex->getITexture()); + CRect rect1(0, 0, width, height); CRect rect2(0, 0, _BlurWidth, _BlurHeight); - // stretch rect - ((CDriverUser *) _Driver)->stretchRect(_Scene, txt1 , rect1, - txt2, rect2); + dru->stretchRect(_Scene, txt1, rect1, txt2, rect2); + _Driver->setMatrixMode2D11(); // horizontal blur pass doBlur(true); @@ -395,7 +277,27 @@ void CBloomEffect::endBloom() // clientcfg doBlur(false); // apply blur with a blend operation + drv->setRenderTarget(renderTarget); + _Driver->setMatrixMode2D11(); applyBlur(); + + // cleanup material texture references + _DisplayBlurMat.getObjectPtr()->setTexture(0, NULL); + _DisplaySquareBlurMat.getObjectPtr()->setTexture(0, NULL); + _DisplaySquareBlurMat.getObjectPtr()->setTexture(1, NULL); + _BlurMat.getObjectPtr()->setTexture(0, NULL); + _BlurMat.getObjectPtr()->setTexture(1, NULL); + _BlurMat.getObjectPtr()->setTexture(2, NULL); + _BlurMat.getObjectPtr()->setTexture(3, NULL); + + // restore + _Driver->enableFog(fogEnabled); + + // recycle render targets + _Driver->getRenderTargetManager().recycleRenderTarget(_BlurFinalTex); + _BlurFinalTex = NULL; + _Driver->getRenderTargetManager().recycleRenderTarget(_BlurHorizontalTex); + _BlurHorizontalTex = NULL; } //----------------------------------------------------------------------------------------------------------- @@ -404,49 +306,6 @@ void CBloomEffect::applyBlur() { NL3D::IDriver *drvInternal = ((CDriverUser *) _Driver)->getDriver(); - /*if (_OriginalRenderTarget) - { - CTextureUser txt(_OriginalRenderTarget); - if(!(static_cast(_Driver)->setRenderTarget(txt, 0, 0, _WndWidth, _WndHeight))) - { - nlwarning("setRenderTarget return false with original render target for bloom effect\n"); - return; - } - } - // in opengl, display in init texture - else if(_InitBloomEffect) - { - CTextureUser txt(_InitText); - if(!(static_cast(_Driver)->setRenderTarget(txt, 0, 0, _WndWidth, _WndHeight))) - { - nlwarning("setRenderTarget return false with initial texture for bloom effect\n"); - return; - } - }*/ - CTextureUser txtApply = _OriginalRenderTarget ? CTextureUser(_OriginalRenderTarget) : ((_InitBloomEffect) ? (CTextureUser(_InitText)) : (CTextureUser())); - if(!(static_cast(_Driver)->setRenderTarget(txtApply, 0, 0, _WndWidth, _WndHeight))) - { - nlwarning("setRenderTarget return false with initial texture for bloom effect\n"); - return; - } - - // display blur texture - // initialize blur texture coordinates - if(_InitBloomEffect) - { - _BlurQuad.Uv0 = CUV(0.f, 0.f); - _BlurQuad.Uv1 = CUV(1.f, 0.f); - _BlurQuad.Uv2 = CUV(1.f, 1.f); - _BlurQuad.Uv3 = CUV(0.f, 1.f); - } - else - { - _BlurQuad.Uv0 = CUV(0.f, 1.f); - _BlurQuad.Uv1 = CUV(1.f, 1.f); - _BlurQuad.Uv2 = CUV(1.f, 0.f); - _BlurQuad.Uv3 = CUV(0.f, 0.f); - } - // initialize vertex program drvInternal->activeVertexProgram(TextureOffsetVertexProgram); drvInternal->setUniform4f(IDriver::VertexProgram, 8, 255.f, 255.f, 255.f, 255.f); @@ -469,59 +328,12 @@ void CBloomEffect::applyBlur() matObjectFinal->texConstantColor(0, constCoeff); // display quad - UCamera pCam = _Scene->getCam(); - _Driver->setMatrixMode2D11(); _Driver->drawQuad(_BlurQuad, displayBlurMat); - _Driver->setMatrixMode3D(pCam); // disable vertex program drvInternal->activeVertexProgram(NULL); } -//----------------------------------------------------------------------------------------------------------- - -void CBloomEffect::endInterfacesDisplayBloom() // clientcfg -{ - // Render from render target to screen if necessary. - // Don't do this when the blend was done to the screen or when rendering to a user provided rendertarget. - if ((_OriginalRenderTarget.getPtr() == NULL) && _InitBloomEffect) - { - if(!_Driver->supportBloomEffect() || !_Init) - return; - - // don't activate bloom when PolygonMode is different from Filled - if (_Driver->getPolygonMode() != UDriver::Filled) return; - - if(_Driver->getWindowWidth()==0 || _Driver->getWindowHeight()==0) - return; - - NL3D::IDriver *drvInternal = ((CDriverUser *) _Driver)->getDriver(); - CTextureUser txtNull; - ((CDriverUser *)_Driver)->setRenderTarget(txtNull, 0, 0, 0, 0); - - // initialize texture coordinates - float newU = drvInternal->isTextureRectangle(_InitText) ? (float)_WndWidth : 1.f; - float newV = drvInternal->isTextureRectangle(_InitText) ? (float)_WndHeight : 1.f; - - _DisplayQuad.Uv0 = CUV(0.f, 0.f); - _DisplayQuad.Uv1 = CUV(newU, 0.f); - _DisplayQuad.Uv2 = CUV(newU, newV); - _DisplayQuad.Uv3 = CUV(0.f, newV); - - // init material texture -// CMaterial * matObjectInit = _DisplayInitMat.getObjectPtr(); - - // display - UCamera pCam = _Scene->getCam(); - _Driver->setMatrixMode2D11(); - _Driver->drawQuad(_DisplayQuad, _DisplayInitMat); - _Driver->setMatrixMode3D(pCam); - } - - _OriginalRenderTarget = NULL; -} - - //----------------------------------------------------------------------------------------------------------- void CBloomEffect::doBlur(bool horizontalBlur) @@ -531,17 +343,17 @@ void CBloomEffect::doBlur(bool horizontalBlur) ITexture * endTexture; // set displayed texture and render target texture of the pass - if(horizontalBlur) + if (horizontalBlur) { blurVec = CVector2f(1.f, 0.f); - startTexture = _BlurFinalTex; - endTexture = _BlurHorizontalTex; + startTexture = _BlurFinalTex->getITexture(); + endTexture = _BlurHorizontalTex->getITexture(); } else { blurVec = CVector2f(0.f, 1.f); - startTexture = _BlurHorizontalTex; - endTexture = _BlurFinalTex; + startTexture = _BlurHorizontalTex->getITexture(); + endTexture = _BlurFinalTex->getITexture(); } NL3D::IDriver *drvInternal = ((CDriverUser *) _Driver)->getDriver(); @@ -552,6 +364,7 @@ void CBloomEffect::doBlur(bool horizontalBlur) nlwarning("setRenderTarget return false with blur texture for bloom effect\n"); return; } + _Driver->setMatrixMode2D11(); // initialize vertex program drvInternal->activeVertexProgram(TextureOffsetVertexProgram); @@ -561,20 +374,30 @@ void CBloomEffect::doBlur(bool horizontalBlur) // set several decal constants in order to obtain in the render target texture a mix of color // of a texel and its neighbored texels on the axe of the pass. float decalL, decal2L, decalR, decal2R; - if(_InitBloomEffect) + if (drvInternal->textureCoordinateAlternativeMode()) + { + if (horizontalBlur) + { + decalL = 0.5f; + decal2L = -0.5f; + decalR = 1.5f; + decal2R = 2.5f; + } + else + { + decalL = 0.0f; + decal2L = -1.0f; + decalR = 1.0f; + decal2R = 2.0f; + } + } + else { decalL = -0.5f; decal2L = -1.5f; decalR = 0.5f; decal2R = 1.5f; } - else - { - decalL = 0.f; - decal2L = -1.f; - decalR = 1.f; - decal2R = 2.f; - } drvInternal->setUniform2f(IDriver::VertexProgram, 10, (decalR/(float)_BlurWidth)*blurVec.x, (decalR/(float)_BlurHeight)*blurVec.y); drvInternal->setUniform2f(IDriver::VertexProgram, 11, (decal2R/(float)_BlurWidth)*blurVec.x, (decal2R/(float)_BlurHeight)*blurVec.y); drvInternal->setUniform2f(IDriver::VertexProgram, 12, (decalL/(float)_BlurWidth)*blurVec.x, (decalL/(float)_BlurHeight)*blurVec.y); @@ -587,22 +410,13 @@ void CBloomEffect::doBlur(bool horizontalBlur) matObject->setTexture(2, startTexture); matObject->setTexture(3, startTexture); - // initialize quad - _BlurQuad.Uv0 = CUV(0.0f, 0.0f); - _BlurQuad.Uv1 = CUV(1.f, 0.0f); - _BlurQuad.Uv2 = CUV(1.f, 1.f); - _BlurQuad.Uv3 = CUV(0.0f, 1.f); - // display - UCamera pCam = _Scene->getCam(); - _Driver->setMatrixMode2D11(); _Driver->drawQuad(_BlurQuad, _BlurMat); // disable render target and vertex program drvInternal->activeVertexProgram(NULL); CTextureUser cu; ((CDriverUser *)_Driver)->setRenderTarget(cu, 0, 0, 0, 0); - _Driver->setMatrixMode3D(pCam); } }; // NL3D diff --git a/code/nel/src/3d/driver.cpp b/code/nel/src/3d/driver.cpp index 2bfb0ea1f..791172700 100644 --- a/code/nel/src/3d/driver.cpp +++ b/code/nel/src/3d/driver.cpp @@ -32,7 +32,7 @@ namespace NL3D { // *************************************************************************** -const uint32 IDriver::InterfaceVersion = 0x6d; // gpu program interface +const uint32 IDriver::InterfaceVersion = 0x6e; // gpu program interface // *************************************************************************** IDriver::IDriver() : _SyncTexDrvInfos( "IDriver::_SyncTexDrvInfos" ) @@ -123,8 +123,9 @@ bool IDriver::release(void) // *************************************************************************** -GfxMode::GfxMode(uint16 w, uint16 h, uint8 d, bool windowed, bool offscreen, uint frequency, sint8 aa) +GfxMode::GfxMode(uint16 w, uint16 h, uint8 d, bool windowed, bool offscreen, uint frequency, sint8 aa, const std::string &displayDevice) { + DisplayDevice = displayDevice; Windowed = windowed; Width = w; Height = h; diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp index c7fd65a99..916cafe49 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp @@ -25,8 +25,6 @@ #include "nel/3d/light.h" #include "nel/3d/index_buffer.h" #include "nel/misc/rect.h" -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/mouse_device.h" #include "nel/misc/dynloadlib.h" #include "nel/3d/viewport.h" #include "nel/3d/scissor.h" @@ -1478,7 +1476,7 @@ bool CDriverD3D::setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool r D3DADAPTER_IDENTIFIER9 Identifier; HRESULT Res; Res = _D3D->GetAdapterIdentifier(gAdapter,0,&Identifier); - + if (strstr(Identifier.Description,"PerfHUD") != 0) { nlinfo ("Setting up with PerfHUD"); @@ -1511,6 +1509,7 @@ bool CDriverD3D::setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool r } } + // _D3D->CreateDevice (adapter, _Rasterizer, _HWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, ¶meters, &_DeviceInterface); // Check some caps @@ -1637,20 +1636,6 @@ bool CDriverD3D::setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool r // Setup the event emitter, and try to retrieve a direct input interface _EventEmitter.addEmitter(we, true /*must delete*/); // the main emitter - // Try to get direct input - try - { - NLMISC::CDIEventEmitter *diee = NLMISC::CDIEventEmitter::create(GetModuleHandle(NULL), _HWnd, we); - if (diee) - { - _EventEmitter.addEmitter(diee, true); - } - } - catch(const EDirectInput &e) - { - nlinfo(e.what()); - } - // Init some variables _ForceDXTCCompression = false; _AnisotropicFilter = 0; @@ -2010,13 +1995,6 @@ bool CDriverD3D::swapBuffers() // todo hulud volatile //_DeviceInterface->SetStreamSource(0, _VolatileVertexBufferRAM[1]->VertexBuffer, 0, 12); - // Is direct input running ? - if (_EventEmitter.getNumEmitters() > 1) - { - // flush direct input messages if any - NLMISC::safe_cast(_EventEmitter.getEmitter(1))->poll(); - } - // End now if (!endScene()) { diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.h b/code/nel/src/3d/driver/direct3d/driver_direct3d.h index 254b21871..039b6f3ed 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.h +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.h @@ -944,6 +944,7 @@ public: virtual ITexture *getRenderTarget() const; virtual bool copyTargetToTexture (ITexture *tex, uint32 offsetx, uint32 offsety, uint32 x, uint32 y, uint32 width, uint32 height, uint32 mipmapLevel); + virtual bool textureCoordinateAlternativeMode() const { return true; }; virtual bool getRenderTargetSize (uint32 &width, uint32 &height); virtual bool fillBuffer (CBitmap &bitmap); @@ -1033,11 +1034,6 @@ public: // Change default scale for all cursors virtual void setCursorScale(float scale); - virtual NLMISC::IMouseDevice *enableLowLevelMouse(bool enable, bool exclusive); - virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable); - virtual NLMISC::IInputDeviceManager *getLowLevelInputDeviceManager(); - virtual uint getDoubleClickDelay(bool hardwareMouse); - // Lights virtual uint getMaxLight () const; virtual void setLight (uint8 num, const CLight& light); diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d_index.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d_index.cpp index 20d59725c..b75a21d9d 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d_index.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d_index.cpp @@ -19,8 +19,6 @@ #include "nel/3d/index_buffer.h" #include "nel/3d/light.h" #include "nel/misc/rect.h" -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/mouse_device.h" #include "nel/3d/viewport.h" #include "nel/3d/scissor.h" #include "nel/3d/u_driver.h" diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d_inputs.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d_inputs.cpp index 4949e2fd8..f754b6357 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d_inputs.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d_inputs.cpp @@ -17,9 +17,6 @@ #include "stddirect3d.h" #include "driver_direct3d.h" -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/mouse_device.h" - using namespace std; using namespace NLMISC; @@ -466,121 +463,6 @@ bool CDriverD3D::isSystemCursorCaptured() return GetCapture() == _HWnd; } -// *************************************************************************** -NLMISC::IMouseDevice* CDriverD3D::enableLowLevelMouse(bool enable, bool exclusive) -{ - H_AUTO_D3D(CDriverD3D_enableLowLevelMouse); - - NLMISC::IMouseDevice *res = NULL; - - NLMISC::CDIEventEmitter *diee = NULL; - - if (_EventEmitter.getNumEmitters() > 1) - diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - - if (enable) - { - try - { - if (diee) - res = diee->getMouseDevice(exclusive); - } - catch (const EDirectInput &) - { - } - } - else - { - if (diee) - diee->releaseMouse(); - } - - return res; -} - -// *************************************************************************** -NLMISC::IKeyboardDevice* CDriverD3D::enableLowLevelKeyboard(bool enable) -{ - H_AUTO_D3D(CDriverD3D_enableLowLevelKeyboard); - - NLMISC::IKeyboardDevice *res = NULL; - - NLMISC::CDIEventEmitter *diee = NULL; - - if (_EventEmitter.getNumEmitters() > 1) - diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - - if (enable) - { - try - { - if (diee) - res = diee->getKeyboardDevice(); - } - catch (const EDirectInput &) - { - } - } - else - { - if (diee) - diee->releaseKeyboard(); - } - - return res; -} - -// *************************************************************************** -NLMISC::IInputDeviceManager* CDriverD3D::getLowLevelInputDeviceManager() -{ - H_AUTO_D3D(CDriverD3D_getLowLevelInputDeviceManager); - - NLMISC::IInputDeviceManager *res = NULL; - - if (_EventEmitter.getNumEmitters() > 1) - res = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - - return res; -} - -// *************************************************************************** -uint CDriverD3D::getDoubleClickDelay(bool hardwareMouse) -{ - H_AUTO_D3D(CDriverD3D_getDoubleClickDelay); - - uint res = 250; - - NLMISC::IMouseDevice *md = NULL; - - if (_EventEmitter.getNumEmitters() >= 2) - { - NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - if (diee->isMouseCreated()) - { - try - { - md = diee->getMouseDevice(hardwareMouse); - } - catch (const EDirectInput &) - { - // could not get device .. - } - } - } - - if (md) - { - res = md->getDoubleClickDelay(); - } - else - { - // try to read the good value from windows - res = ::GetDoubleClickTime(); - } - - return res; -} - bool CDriverD3D::convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY) { return convertBitmapToIcon(bitmap, cursor, iconWidth, iconHeight, iconDepth, col, hotSpotX, hotSpotY, true); diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d_light.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d_light.cpp index 4ad5b46c0..d3bb62e64 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d_light.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d_light.cpp @@ -20,8 +20,6 @@ #include "nel/3d/light.h" #include "nel/3d/index_buffer.h" #include "nel/misc/rect.h" -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/mouse_device.h" #include "nel/3d/viewport.h" #include "nel/3d/scissor.h" #include "nel/3d/u_driver.h" diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d_material.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d_material.cpp index 40d01039b..f22cba111 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d_material.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d_material.cpp @@ -21,8 +21,6 @@ #include "nel/3d/index_buffer.h" #include "nel/3d/texture_bump.h" #include "nel/misc/rect.h" -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/mouse_device.h" #include "nel/3d/viewport.h" #include "nel/3d/scissor.h" #include "nel/3d/u_driver.h" @@ -648,7 +646,7 @@ bool CDriverD3D::setupMaterial(CMaterial &mat) // Must separate texture setup and texture activation in 2 "for"... // because setupTexture() may disable all stage. - if (matShader == CMaterial::Normal + if (matShader == CMaterial::Normal || ((matShader == CMaterial::Program) && (_PixelProgramUser->features().MaterialFlags & CProgramFeatures::TextureStages)) ) { @@ -670,7 +668,7 @@ bool CDriverD3D::setupMaterial(CMaterial &mat) // Don't do it also for Specular because the EnvFunction and the TexGen may be special. { H_AUTO_D3D(CDriverD3D_setupMaterial_normalShaderActivateTextures) - if (matShader == CMaterial::Normal + if (matShader == CMaterial::Normal || ((matShader == CMaterial::Program) && (_PixelProgramUser->features().MaterialFlags & CProgramFeatures::TextureStages)) ) { diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d_matrix.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d_matrix.cpp index 87b047476..c5b479de0 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d_matrix.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d_matrix.cpp @@ -20,8 +20,6 @@ #include "nel/3d/light.h" #include "nel/3d/index_buffer.h" #include "nel/misc/rect.h" -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/mouse_device.h" #include "nel/3d/viewport.h" #include "nel/3d/scissor.h" #include "nel/3d/u_driver.h" diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d_render.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d_render.cpp index 313fb2344..939dc1dc9 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d_render.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d_render.cpp @@ -20,8 +20,6 @@ #include "nel/3d/light.h" #include "nel/3d/index_buffer.h" #include "nel/misc/rect.h" -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/mouse_device.h" #include "nel/misc/fast_mem.h" #include "nel/3d/viewport.h" #include "nel/3d/scissor.h" diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d_texture.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d_texture.cpp index 2995c5b4c..ad5de53c1 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d_texture.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d_texture.cpp @@ -20,8 +20,6 @@ #include "nel/3d/light.h" #include "nel/3d/index_buffer.h" #include "nel/misc/rect.h" -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/mouse_device.h" #include "nel/3d/viewport.h" #include "nel/3d/scissor.h" #include "nel/3d/u_driver.h" diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d_vertex.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d_vertex.cpp index b798acb26..d37c272a2 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d_vertex.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d_vertex.cpp @@ -20,8 +20,6 @@ #include "nel/3d/light.h" #include "nel/3d/index_buffer.h" #include "nel/misc/rect.h" -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/mouse_device.h" #include "nel/3d/viewport.h" #include "nel/3d/scissor.h" #include "nel/3d/u_driver.h" diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.cpp b/code/nel/src/3d/driver/opengl/driver_opengl.cpp index 6dae9f4fe..e9965e0f1 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl.cpp @@ -28,8 +28,6 @@ #include "nel/3d/light.h" #include "nel/3d/index_buffer.h" #include "nel/misc/rect.h" -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/mouse_device.h" #include "nel/misc/hierarchical_timer.h" #include "nel/misc/dynloadlib.h" #include "driver_opengl_vertex_buffer_hard.h" @@ -236,6 +234,10 @@ CDriverGL::CDriverGL() _CursorScale = 1.f; _MouseCaptured = false; +#if defined(NL_OS_WINDOWS) + _BorderlessFullscreen = false; +#endif + _NeedToRestaureGammaRamp = false; _win = EmptyWindow; @@ -483,7 +485,7 @@ bool CDriverGL::setupDisplay() glLightModeli((GLenum)GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SEPARATE_SPECULAR_COLOR_EXT); #endif } - + if (_Extensions.ARBFragmentShader) { _ForceNativeFragmentPrograms = false; @@ -936,14 +938,6 @@ bool CDriverGL::swapBuffers() } #endif -#ifdef NL_OS_WINDOWS - if (_EventEmitter.getNumEmitters() > 1) // is direct input running ? - { - // flush direct input messages if any - NLMISC::safe_cast(_EventEmitter.getEmitter(1))->poll(); - } -#endif - if (!_WndActive) { if (_AGPVertexArrayRange) _AGPVertexArrayRange->updateLostBuffers(); @@ -1042,6 +1036,8 @@ bool CDriverGL::release() // Call IDriver::release() before, to destroy textures, shaders and VBs... IDriver::release(); + nlassert(_DepthStencilFBOs.empty()); + _SwapBufferCounter = 0; // delete querries @@ -1085,7 +1081,7 @@ void CDriverGL::setupViewport (const class CViewport& viewport) // Setup gl viewport uint32 clientWidth, clientHeight; - getWindowSize(clientWidth, clientHeight); + getRenderTargetSize(clientWidth, clientHeight); // Backup the viewport _CurrViewport = viewport; @@ -1140,7 +1136,7 @@ void CDriverGL::setupScissor (const class CScissor& scissor) // Setup gl viewport uint32 clientWidth, clientHeight; - getWindowSize(clientWidth, clientHeight); + getRenderTargetSize(clientWidth, clientHeight); // Backup the scissor _CurrScissor= scissor; @@ -1509,7 +1505,7 @@ void CDriverGL::enableUsedTextureMemorySum (bool enable) H_AUTO_OGL(CDriverGL_enableUsedTextureMemorySum ) if (enable) - { + { nlinfo ("3D: PERFORMANCE INFO: enableUsedTextureMemorySum has been set to true in CDriverGL"); _TextureUsed.reserve(512); } diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.h b/code/nel/src/3d/driver/opengl/driver_opengl.h index 241b3bb95..fb6069447 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.h +++ b/code/nel/src/3d/driver/opengl/driver_opengl.h @@ -146,6 +146,23 @@ public: virtual uint getVisibleCount(); }; +// *************************************************************************** +class CDepthStencilFBO : public NLMISC::CRefCount +{ +public: + CDepthStencilFBO(CDriverGL *driver, uint width, uint height); + ~CDepthStencilFBO(); + + uint Width; + uint Height; + + GLuint DepthFBOId; + GLuint StencilFBOId; + +private: + CDriverGL *m_Driver; +}; + // *************************************************************************** class CTextureDrvInfosGL : public ITextureDrvInfos { @@ -173,12 +190,9 @@ public: GLuint FBOId; // depth stencil FBO id - GLuint DepthFBOId; - GLuint StencilFBOId; - - bool InitFBO; bool AttachDepthStencil; - bool UsePackedDepthStencil; + NLMISC::CSmartPtr DepthStencilFBO; + bool InitFBO; // The current wrap modes assigned to the texture. ITexture::TWrapMode WrapS; @@ -527,14 +541,6 @@ public: // Change default scale for all cursors virtual void setCursorScale(float scale); - virtual NLMISC::IMouseDevice *enableLowLevelMouse(bool enable, bool exclusive); - - virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable); - - virtual NLMISC::IInputDeviceManager *getLowLevelInputDeviceManager(); - - virtual uint getDoubleClickDelay(bool hardwareMouse); - virtual void getWindowSize (uint32 &width, uint32 &height); virtual void getWindowPos (sint32 &x, sint32 &y); @@ -566,6 +572,8 @@ public: virtual bool copyTargetToTexture (ITexture *tex, uint32 offsetx, uint32 offsety, uint32 x, uint32 y, uint32 width, uint32 height, uint32 mipmapLevel); + virtual bool textureCoordinateAlternativeMode() const { return false; }; + virtual bool getRenderTargetSize (uint32 &width, uint32 &height); @@ -693,6 +701,7 @@ private: friend class CTextureDrvInfosGL; friend class CVertexProgamDrvInfosGL; friend class CPixelProgamDrvInfosGL; + friend class CDepthStencilFBO; private: // Version of the driver. Not the interface version!! Increment when implementation of the driver change. @@ -888,8 +897,11 @@ private: // viewport before call to setRenderTarget, if BFO extension is supported CViewport _OldViewport; + // Current FBO render target CSmartPtr _RenderTargetFBO; + // Share the same backbuffer for FBO render targets with window size + std::vector _DepthStencilFBOs; // Num lights return by GL_MAX_LIGHTS uint _MaxDriverLight; @@ -984,6 +996,12 @@ private: EWindowStyle getWindowStyle() const; bool setWindowStyle(EWindowStyle windowStyle); +#if defined(NL_OS_WINDOWS) + static BOOL CALLBACK monitorEnumProcFullscreen(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData); + bool _BorderlessFullscreen; +#endif + std::string _CurrentDisplayDevice; + // Methods to manage screen resolutions bool restoreScreenMode(); bool saveScreenMode(); diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_inputs.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_inputs.cpp index d1cd1fb60..cbd1bcd9a 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_inputs.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_inputs.cpp @@ -27,8 +27,6 @@ # endif // HAVE_XCURSOR #endif // defined(NL_OS_UNIX) && !defined(NL_OS_MAC) -#include "nel/misc/mouse_device.h" -#include "nel/misc/di_event_emitter.h" #include "nel/3d/u_driver.h" #include "nel/misc/file.h" @@ -666,149 +664,6 @@ bool CDriverGL::isSystemCursorCaptured() #endif } -// *************************************************************************** -NLMISC::IMouseDevice* CDriverGL::enableLowLevelMouse(bool enable, bool exclusive) -{ - H_AUTO_OGL(CDriverGL_enableLowLevelMouse); - - NLMISC::IMouseDevice *res = NULL; - -#ifdef NL_OS_WINDOWS - - NLMISC::CDIEventEmitter *diee = NULL; - - if (_EventEmitter.getNumEmitters() > 1) - diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - - if (enable) - { - try - { - if (diee) - res = diee->getMouseDevice(exclusive); - } - catch (const EDirectInput &) - { - } - } - else - { - if (diee) - diee->releaseMouse(); - } - -#elif defined(NL_OS_MAC) -#elif defined (NL_OS_UNIX) -#endif - - return res; -} - -// *************************************************************************** -NLMISC::IKeyboardDevice* CDriverGL::enableLowLevelKeyboard(bool enable) -{ - H_AUTO_OGL(CDriverGL_enableLowLevelKeyboard); - - NLMISC::IKeyboardDevice *res = NULL; - -#ifdef NL_OS_WINDOWS - - NLMISC::CDIEventEmitter *diee = NULL; - - if (_EventEmitter.getNumEmitters() > 1) - diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - - if (enable) - { - try - { - if (diee) - res = diee->getKeyboardDevice(); - } - catch (const EDirectInput &) - { - } - } - else - { - if (diee) - diee->releaseKeyboard(); - } - -#elif defined(NL_OS_MAC) -#elif defined (NL_OS_UNIX) -#endif - - return res; -} - -// *************************************************************************** -NLMISC::IInputDeviceManager* CDriverGL::getLowLevelInputDeviceManager() -{ - H_AUTO_OGL(CDriverGL_getLowLevelInputDeviceManager); - - NLMISC::IInputDeviceManager *res = NULL; - -#ifdef NL_OS_WINDOWS - - if (_EventEmitter.getNumEmitters() > 1) - res = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - -#elif defined(NL_OS_MAC) -#elif defined (NL_OS_UNIX) -#endif - - return res; -} - -// *************************************************************************** -uint CDriverGL::getDoubleClickDelay(bool hardwareMouse) -{ - H_AUTO_OGL(CDriverGL_getDoubleClickDelay); - - uint res = 250; - -#ifdef NL_OS_WINDOWS - - NLMISC::IMouseDevice *md = NULL; - - if (_EventEmitter.getNumEmitters() >= 2) - { - NLMISC::CDIEventEmitter *diee = NLMISC::safe_cast(_EventEmitter.getEmitter(1)); - if (diee->isMouseCreated()) - { - try - { - md = diee->getMouseDevice(hardwareMouse); - } - catch (const EDirectInput &) - { - // could not get device .. - } - } - } - - if (md) - { - res = md->getDoubleClickDelay(); - } - else - { - // try to read the good value from windows - res = ::GetDoubleClickTime(); - } - -#elif defined(NL_OS_MAC) - // TODO: Missing Mac Implementation for getDoubleClickDelay -#elif defined (NL_OS_UNIX) - - // TODO for Linux - -#endif - - return res; -} - bool CDriverGL::getBestCursorSize(uint srcWidth, uint srcHeight, uint &dstWidth, uint &dstHeight) { #ifdef NL_OS_WINDOWS diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_material.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_material.cpp index ed43fe8c3..986dd6303 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_material.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_material.cpp @@ -2087,14 +2087,16 @@ void CDriverGL::setupCloudPass (uint /* pass */) glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA); activateTexEnvColor (1, mat.getColor()); } - else + else if (ATICloudShaderHandle) { // TODO : for now the state is not cached in _CurrentTexEnvSpecial nglBindFragmentShaderATI(ATICloudShaderHandle); glEnable(GL_FRAGMENT_SHADER_ATI); float cst[4] = { 0.f, 0.f, 0.f, mat.getColor().A / 255.f }; nglSetFragmentShaderConstantATI(GL_CON_0_ATI, cst); - /* + } + else + { _DriverGLStates.activeTextureARB(0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); // Operator. @@ -2130,7 +2132,6 @@ void CDriverGL::setupCloudPass (uint /* pass */) glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_CONSTANT_EXT ); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA); - */ } #endif } diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_texture.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_texture.cpp index f26b53254..9b798ae51 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_texture.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_texture.cpp @@ -73,12 +73,8 @@ CTextureDrvInfosGL::CTextureDrvInfosGL(IDriver *drv, ItTexDrvInfoPtrMap it, CDri #endif FBOId = 0; - DepthFBOId = 0; - StencilFBOId = 0; - InitFBO = false; AttachDepthStencil = true; - UsePackedDepthStencil = drvGl->supportPackedDepthStencil(); TextureUsedIdx = 0; } @@ -98,9 +94,9 @@ CTextureDrvInfosGL::~CTextureDrvInfosGL() _Driver->_TextureUsed[TextureUsedIdx] = NULL; } - if(InitFBO) - { #ifdef USE_OPENGLES + if (InitFBO) + { nglDeleteFramebuffersOES(1, &FBOId); if(AttachDepthStencil) { @@ -108,24 +104,73 @@ CTextureDrvInfosGL::~CTextureDrvInfosGL() if(!UsePackedDepthStencil) nglDeleteRenderbuffersOES(1, &StencilFBOId); } -#else - nglDeleteFramebuffersEXT(1, &FBOId); - if(AttachDepthStencil) - { - nglDeleteRenderbuffersEXT(1, &DepthFBOId); - if(!UsePackedDepthStencil) - nglDeleteRenderbuffersEXT(1, &StencilFBOId); - } + } #endif +} + +CDepthStencilFBO::CDepthStencilFBO(CDriverGL *driver, uint width, uint height) +{ + nldebug("3D: Init shared FBO"); + + m_Driver = driver; + Width = width; + Height = height; + + bool packedDepthStencil = driver->supportPackedDepthStencil(); + nglGenRenderbuffersEXT(1, &DepthFBOId); + if (packedDepthStencil) + StencilFBOId = DepthFBOId; + else + nglGenRenderbuffersEXT(1, &StencilFBOId); + + if (packedDepthStencil) + { + //nldebug("3D: using packed depth stencil"); + nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilFBOId); + nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, width, height); + } + else + { + nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthFBOId); + nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height); + /* + nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilFBOId); + nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, width, height); + */ + } + + nlassert(DepthFBOId); + nlassert(StencilFBOId); + + driver->_DepthStencilFBOs.push_back(this); +} + +CDepthStencilFBO::~CDepthStencilFBO() +{ + // driver remove + m_Driver->_DepthStencilFBOs.erase(std::find(m_Driver->_DepthStencilFBOs.begin(), m_Driver->_DepthStencilFBOs.end(), this)); + + if (DepthFBOId) + { + nldebug("3D: Release shared FBO"); + nglDeleteRenderbuffersEXT(1, &DepthFBOId); + if (StencilFBOId == DepthFBOId) + StencilFBOId = 0; + DepthFBOId = 0; + } + if (StencilFBOId) + { + nglDeleteRenderbuffersEXT(1, &StencilFBOId); + StencilFBOId = 0; } } // *************************************************************************** bool CTextureDrvInfosGL::initFrameBufferObject(ITexture * tex) { - if(!InitFBO) + if (!InitFBO) { - if(tex->isBloomTexture()) + if (tex->isBloomTexture()) { AttachDepthStencil = !((CTextureBloom*)tex)->isMode2D(); } @@ -179,49 +224,33 @@ bool CTextureDrvInfosGL::initFrameBufferObject(ITexture * tex) #else // generate IDs nglGenFramebuffersEXT(1, &FBOId); - if(AttachDepthStencil) - { - nglGenRenderbuffersEXT(1, &DepthFBOId); - if(UsePackedDepthStencil) - StencilFBOId = DepthFBOId; - else - nglGenRenderbuffersEXT(1, &StencilFBOId); - } - + //nldebug("3D: using depth %d and stencil %d", DepthFBOId, StencilFBOId); // initialize FBO nglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBOId); nglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, TextureMode, ID, 0); - // attach depth/stencil render to FBO - // note: for some still unkown reason it's impossible to add - // a stencil buffer as shown in the respective docs (see - // opengl.org extension registry). Until a safe approach to add - // them is found, there will be no attached stencil for the time - // being, aside of using packed depth+stencil buffers. - if(AttachDepthStencil) + // attach depth stencil + if (AttachDepthStencil) { - if(UsePackedDepthStencil) + for (std::vector::iterator it(_Driver->_DepthStencilFBOs.begin()), end(_Driver->_DepthStencilFBOs.end()); it != end; ++it) { - //nldebug("3D: using packed depth stencil"); - nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilFBOId); - nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, tex->getWidth(), tex->getHeight()); + if ((*it)->Width == tex->getWidth() && (*it)->Height == tex->getHeight()) + { + DepthStencilFBO = (*it); + break; + } } - else + if (!DepthStencilFBO) { - nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthFBOId); - nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, tex->getWidth(), tex->getHeight()); - /* - nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilFBOId); - nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, tex->getWidth(), tex->getHeight()); - */ + DepthStencilFBO = new CDepthStencilFBO(_Driver, tex->getWidth(), tex->getHeight()); } nglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, DepthFBOId); + GL_RENDERBUFFER_EXT, DepthStencilFBO->DepthFBOId); nldebug("3D: glFramebufferRenderbufferExt(depth:24) = %X", nglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); nglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, StencilFBOId); + GL_RENDERBUFFER_EXT, DepthStencilFBO->StencilFBOId); nldebug("3D: glFramebufferRenderbufferExt(stencil:8) = %X", nglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); } #endif @@ -339,17 +368,7 @@ bool CTextureDrvInfosGL::initFrameBufferObject(ITexture * tex) #endif if (AttachDepthStencil) { -#ifdef USE_OPENGLES - nglDeleteRenderbuffersOES(1, &DepthFBOId); -#else - nglDeleteRenderbuffersEXT(1, &DepthFBOId); -#endif - if(!UsePackedDepthStencil) -#ifdef USE_OPENGLES - nglDeleteRenderbuffersOES(1, &StencilFBOId); -#else - nglDeleteRenderbuffersEXT(1, &StencilFBOId); -#endif + DepthStencilFBO = NULL; } } @@ -2260,11 +2279,8 @@ void CDriverGL::swapTextureHandle(ITexture &tex0, ITexture &tex1) swap(t0->MinFilter, t1->MinFilter); swap(t0->TextureMode, t1->TextureMode); swap(t0->FBOId, t1->FBOId); - swap(t0->DepthFBOId, t1->DepthFBOId); - swap(t0->StencilFBOId, t1->StencilFBOId); + swap(t0->DepthStencilFBO, t1->DepthStencilFBO); swap(t0->InitFBO, t1->InitFBO); - swap(t0->AttachDepthStencil, t1->AttachDepthStencil); - swap(t0->UsePackedDepthStencil, t1->UsePackedDepthStencil); } @@ -2314,11 +2330,16 @@ bool CDriverGL::setRenderTarget (ITexture *tex, uint32 x, uint32 y, uint32 width if(tex->isBloomTexture() && supportBloomEffect()) { + // NOTE: No support for mip map level here! + uint32 w, h; getWindowSize(w, h); getViewport(_OldViewport); + if (!width) width = tex->getWidth(); + if (!height) height = tex->getHeight(); + CViewport newVP; newVP.init(0, 0, ((float)width/(float)w), ((float)height/(float)h)); setupViewport(newVP); @@ -2401,10 +2422,11 @@ bool CDriverGL::copyTargetToTexture (ITexture *tex, bool CDriverGL::getRenderTargetSize (uint32 &width, uint32 &height) { H_AUTO_OGL(CDriverGL_getRenderTargetSize) - if (_TextureTarget) + NLMISC::CSmartPtr tex = _RenderTargetFBO ? _RenderTargetFBO : (_TextureTarget ? _TextureTarget : NULL); + if (tex) { - width = _TextureTarget->getWidth(); - height = _TextureTarget->getHeight(); + width = tex->getWidth(); + height = tex->getHeight(); } else { diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp index 2fea530cf..4e08884b0 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp @@ -38,8 +38,6 @@ # define _NET_WM_STATE_ADD 1 #endif // NL_OS_UNIX -#include "nel/misc/mouse_device.h" -#include "nel/misc/di_event_emitter.h" #include "nel/3d/u_driver.h" #include "nel/misc/file.h" @@ -255,7 +253,7 @@ bool GlWndProc(CDriverGL *driver, XEvent &e) unsigned long nitems_return = 0; unsigned long bytes_after_return = 0; long *data = NULL; - + int status = XGetWindowProperty(driver->_dpy, driver->_win, XA_FRAME_EXTENTS, 0, 4, False, XA_CARDINAL, &type_return, &format_return, &nitems_return, &bytes_after_return, (unsigned char**)&data); // succeeded to retrieve decoration size @@ -270,7 +268,7 @@ bool GlWndProc(CDriverGL *driver, XEvent &e) driver->_DecorationWidth = e.xconfigure.x - driver->_WindowX; driver->_DecorationHeight = e.xconfigure.y - driver->_WindowY; } - + // don't allow negative decoration sizes if (driver->_DecorationWidth < 0) driver->_DecorationWidth = 0; if (driver->_DecorationHeight < 0) driver->_DecorationHeight = 0; @@ -940,20 +938,6 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re // setup the event emitter, and try to retrieve a direct input interface _EventEmitter.addEmitter(we, true /*must delete*/); // the main emitter - /// try to get direct input - try - { - NLMISC::CDIEventEmitter *diee = NLMISC::CDIEventEmitter::create(GetModuleHandle(NULL), _win, we); - if (diee) - { - _EventEmitter.addEmitter(diee, true); - } - } - catch(const EDirectInput &e) - { - nlinfo(e.what()); - } - #elif defined(NL_OS_MAC) if (wnd == EmptyWindow) @@ -1287,10 +1271,86 @@ static sint modeInfoToFrequency(XF86VidModeModeInfo *info) // *************************************************************************** +#if defined(NL_OS_WINDOWS) + +struct CMonitorEnumParams +{ +public: + CDriverGL *Driver; + const char *DeviceName; + bool Success; +}; + +BOOL CALLBACK CDriverGL::monitorEnumProcFullscreen(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData) +{ + CMonitorEnumParams *p = reinterpret_cast(dwData); + + MONITORINFOEXA monitorInfo; + memset(&monitorInfo, 0, sizeof(monitorInfo)); + monitorInfo.cbSize = sizeof(monitorInfo); + GetMonitorInfoA(hMonitor, &monitorInfo); + nldebug("3D: Monitor: '%s'", monitorInfo.szDevice); + + size_t devLen = strlen(monitorInfo.szDevice); + size_t targetLen = strlen(p->DeviceName); + + nlassert(devLen < 32); + size_t minLen = min(devLen, targetLen); + if (!memcmp(monitorInfo.szDevice, p->DeviceName, minLen)) + { + if (devLen == targetLen + || (devLen < targetLen && (p->DeviceName[minLen] == '\\')) + || (devLen > targetLen && (monitorInfo.szDevice[minLen] == '\\'))) + { + nldebug("3D: Remapping '%s' to '%s'", p->DeviceName, monitorInfo.szDevice); + nldebug("3D: Found requested monitor at %i, %i", monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top); + p->Driver->_CurrentMode.Windowed = false; + p->Driver->setWindowStyle(CDriverGL::EWSWindowed); + p->Driver->setWindowSize(monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top); + LONG dwStyle = GetWindowLong(p->Driver->_win, GWL_STYLE); + SetWindowLong(p->Driver->_win, GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW); + SetWindowPos(p->Driver->_win, NULL, + monitorInfo.rcMonitor.left, + monitorInfo.rcMonitor.top, + monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left, + monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top, + SWP_FRAMECHANGED); + p->Driver->_WindowX = monitorInfo.rcMonitor.left; + p->Driver->_WindowY = monitorInfo.rcMonitor.top; + p->Driver->_CurrentDisplayDevice = std::string(p->DeviceName); + p->Driver->_BorderlessFullscreen = true; + p->Driver->_CurrentMode.Windowed = false; + p->Success = true; + return FALSE; + } + } + p->Success = false; + return TRUE; // continue +}; + +#endif + +// *************************************************************************** + bool CDriverGL::setScreenMode(const GfxMode &mode) { H_AUTO_OGL(CDriverGL_setScreenMode) + nldebug("3D: setScreenMode"); + +#if defined(NL_OS_WINDOWS) + if (_BorderlessFullscreen) + { + _BorderlessFullscreen = false; + LONG dwStyle = GetWindowLong(_win, GWL_STYLE); + dwStyle |= WS_OVERLAPPEDWINDOW; + if (!_Resizable) dwStyle ^= WS_MAXIMIZEBOX|WS_THICKFRAME; + SetWindowLong(_win, GWL_STYLE, dwStyle); + SetWindowPos(_win, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + _CurrentMode.Windowed = true; + } +#endif + if (mode.Windowed) { // if fullscreen, switch back to desktop screen mode @@ -1300,13 +1360,17 @@ bool CDriverGL::setScreenMode(const GfxMode &mode) return true; } + if (_CurrentDisplayDevice != mode.DisplayDevice) + restoreScreenMode(); + // save previous screen mode only if switching from windowed to fullscreen if (_CurrentMode.Windowed) saveScreenMode(); // if switching exactly to the same screen mode, doesn't change it GfxMode previousMode; - if (getCurrentScreenMode(previousMode) + if (_CurrentDisplayDevice == mode.DisplayDevice + && getCurrentScreenMode(previousMode) && mode.Width == previousMode.Width && mode.Height == previousMode.Height && mode.Depth == previousMode.Depth @@ -1315,7 +1379,9 @@ bool CDriverGL::setScreenMode(const GfxMode &mode) #if defined(NL_OS_WINDOWS) - DEVMODE devMode; + const char *deviceName = mode.DisplayDevice.c_str(); + + DEVMODEA devMode; memset(&devMode, 0, sizeof(DEVMODE)); devMode.dmSize = sizeof(DEVMODE); devMode.dmDriverExtra = 0; @@ -1323,22 +1389,42 @@ bool CDriverGL::setScreenMode(const GfxMode &mode) devMode.dmPelsWidth = mode.Width; devMode.dmPelsHeight = mode.Height; - if(mode.Depth > 0) + if (mode.Depth > 0) { devMode.dmBitsPerPel = mode.Depth; devMode.dmFields |= DM_BITSPERPEL; } - if(mode.Frequency > 0) + if (mode.Frequency > 0) { devMode.dmDisplayFrequency = mode.Frequency; devMode.dmFields |= DM_DISPLAYFREQUENCY; } - - if (ChangeDisplaySettings(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + + if (deviceName[0]) { - nlwarning("3D: Fullscreen mode switch failed"); - return false; + // First attempt exclusive fullscreen + nldebug("3D: ChangeDisplaySettingsEx"); + LONG resex; + if ((resex = ChangeDisplaySettingsExA(deviceName, &devMode, NULL, CDS_FULLSCREEN, NULL)) != DISP_CHANGE_SUCCESSFUL) + { + nlwarning("3D: Fullscreen mode switch failed (%i)", (sint)resex); + // Workaround, resize to monitor and make borderless + CMonitorEnumParams p; + p.DeviceName = deviceName; + p.Driver = this; + EnumDisplayMonitors(NULL, NULL, monitorEnumProcFullscreen, (LPARAM)&p); + return p.Success; + } + } + else + { + nldebug("3D: ChangeDisplaySettings"); + if (ChangeDisplaySettingsA(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + { + nlwarning("3D: Fullscreen mode switch failed"); + return false; + } } #elif defined(NL_OS_MAC) @@ -1744,7 +1830,11 @@ bool CDriverGL::setWindowStyle(EWindowStyle windowStyle) dwNewStyle |= WS_VISIBLE; if (dwStyle != dwNewStyle) + { SetWindowLong(_win, GWL_STYLE, dwNewStyle); + if (windowStyle == EWSWindowed) + SetWindowPos(_win, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); + } // if (windowStyle == EWSMaximized && isVisible && !isMaximized) // ShowWindow(_hWnd, SW_SHOWMAXIMIZED); @@ -1864,17 +1954,32 @@ bool CDriverGL::setMode(const GfxMode& mode) if (!_DestroyWindow) return true; +#if defined(NL_OS_WINDOWS) + // save relative cursor + POINT cursorPos; + BOOL cursorPosOk = isSystemCursorInClientArea() + && GetCursorPos(&cursorPos) + && ScreenToClient(_win, &cursorPos); + sint curX = (sint)cursorPos.x * (sint)mode.Width; + sint curY = (sint)cursorPos.y * (sint)mode.Height; + if (_BorderlessFullscreen) + ReleaseCapture(); +#endif + if (!setScreenMode(mode)) return false; - // when changing window style, it's possible system change window size too - setWindowStyle(mode.Windowed ? EWSWindowed : EWSFullscreen); + if (!_BorderlessFullscreen) + { + // when changing window style, it's possible system change window size too + setWindowStyle(mode.Windowed ? EWSWindowed : EWSFullscreen); - if (!mode.Windowed) - _CurrentMode.Depth = mode.Depth; + if (!mode.Windowed) + _CurrentMode.Depth = mode.Depth; - setWindowSize(mode.Width, mode.Height); - setWindowPos(_WindowX, _WindowY); + setWindowSize(mode.Width, mode.Height); + setWindowPos(_WindowX, _WindowY); + } switch (_CurrentMode.Depth) { @@ -1883,6 +1988,19 @@ bool CDriverGL::setMode(const GfxMode& mode) case 32: _ColorDepth = ColorDepth32; break; } +#if defined(NL_OS_WINDOWS) + // restore relative cursor + if (cursorPosOk) + { + cursorPos.x = curX / (sint)mode.Width; + cursorPos.y = curY / (sint)mode.Height; + ClientToScreen(_win, &cursorPos); + SetCursorPos(cursorPos.x, cursorPos.y); + if (_BorderlessFullscreen) + SetCapture(_win); + } +#endif + // set color depth for custom cursor updateCursor(true); @@ -2298,7 +2416,19 @@ void CDriverGL::setWindowPos(sint32 x, sint32 y) #ifdef NL_OS_WINDOWS - SetWindowPos(_win, NULL, x, y, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE); + // save relative cursor + POINT cursorPos; + BOOL cursorPosOk = isSystemCursorInClientArea() + && GetCursorPos(&cursorPos) + && ScreenToClient(_win, &cursorPos); + + SetWindowPos(_win, NULL, x, y, 0, 0, /*SWP_NOZORDER | SWP_NOACTIVATE |*/ SWP_NOSIZE); + + if (cursorPosOk) + { + ClientToScreen(_win, &cursorPos); + SetCursorPos(cursorPos.x, cursorPos.y); + } #elif defined(NL_OS_MAC) // get the rect (position, size) of the screen with menu bar @@ -2469,7 +2599,7 @@ bool CDriverGL::createContext() if (_EglContext == EGL_NO_CONTEXT) { return false; - } + } // Make the context current if (!eglMakeCurrent(_EglDisplay, _EglSurface, _EglSurface, _EglContext)) diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h index 7e46fc6de..aa7d591fd 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_event_emitter.h @@ -20,14 +20,13 @@ #include "nel/misc/event_emitter.h" #include "nel/misc/event_server.h" #include "nel/misc/events.h" -#include "nel/misc/game_device_events.h" #include "nel/3d/driver.h" #import "cocoa_opengl_view.h" #include #import -namespace NLMISC +namespace NLMISC { class CCocoaEventEmitter : public IEventEmitter @@ -42,8 +41,8 @@ class CCocoaEventEmitter : public IEventEmitter CEventServer* _server; public: - CCocoaEventEmitter() : - _emulateRawMode(false), + CCocoaEventEmitter() : + _emulateRawMode(false), _setToEmulateRawMode(false), _driver(NULL), _glView(nil), @@ -52,7 +51,6 @@ public: void init(NL3D::IDriver*, CocoaOpenGLView*, bool eventLoop); bool processMessage(NSEvent* event, CEventServer* server = NULL); virtual void submitEvents(CEventServer& server, bool allWindows); - virtual void emulateMouseRawMode(bool enable); bool handleQuitRequest(); virtual bool copyTextToClipboard(const ucstring &text); diff --git a/code/nel/src/3d/driver/opengl/stdopengl.h b/code/nel/src/3d/driver/opengl/stdopengl.h index 9773b0048..ab4eb8316 100644 --- a/code/nel/src/3d/driver/opengl/stdopengl.h +++ b/code/nel/src/3d/driver/opengl/stdopengl.h @@ -83,7 +83,6 @@ #include "nel/misc/event_emitter_multi.h" #include "nel/misc/time_nl.h" #include "nel/misc/rect.h" -#include "nel/misc/mouse_device.h" #include "nel/misc/dynloadlib.h" #include "nel/misc/file.h" diff --git a/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp b/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp index c3a8552ac..be0736bae 100644 --- a/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp +++ b/code/nel/src/3d/driver/opengl/unix_event_emitter.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "nel/misc/debug.h" @@ -37,7 +37,7 @@ static Atom XA_WM_DELETE_WINDOW = 0; namespace NLMISC { -CUnixEventEmitter::CUnixEventEmitter ():_dpy(NULL), _win(0), _emulateRawMode(false), _driver(NULL) +CUnixEventEmitter::CUnixEventEmitter ():_dpy(NULL), _win(0), _driver(NULL) { _im = 0; _ic = 0; @@ -158,25 +158,6 @@ static Bool isMouseMoveEvent(Display *display, XEvent *event, XPointer arg) return (event->type == MotionNotify); } -void CUnixEventEmitter::emulateMouseRawMode(bool enable) -{ - _emulateRawMode = enable; - - if(_emulateRawMode) - { - XWindowAttributes xwa; - XGetWindowAttributes(_dpy, _win, &xwa); - XWarpPointer(_dpy, None, _win, None, None, None, None, - (xwa.width / 2), (xwa.height / 2)); - - // remove all outstanding mouse move events, they happened before the mouse - // was pulled back to 0.5 / 0.5, so a wrong movement delta would be - // reported otherwise - XEvent event; - while(XCheckIfEvent(_dpy, &event, &isMouseMoveEvent, NULL)) { }; - } -} - #ifndef AltMask # ifdef NL_OS_MAC # define AltMask (8192) @@ -512,33 +493,13 @@ bool CUnixEventEmitter::processMessage (XEvent &event, CEventServer *server) { TMouseButton button=getMouseButton (event.xbutton.state); - // if raw mode should be emulated - if(_emulateRawMode) - { - // when we just wrapped back the pointer to 0.5 / 0.5, ignore event - if(event.xbutton.x == xwa.width / 2 && event.xbutton.y == xwa.height / 2) - break; + // get the relative mouse position + float fX = (float) event.xbutton.x / (float) xwa.width; + float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height; - // post a CGDMouseMove with the movement delta to the event server - server->postEvent( - new CGDMouseMove(this, NULL /* no mouse device */, - event.xbutton.x - (xwa.width / 2), - (xwa.height / 2) - event.xbutton.y)); + // post a normal mouse move event to the event server + server->postEvent (new CEventMouseMove (fX, fY, button, this)); - // move the pointer back to the center of the window - XWarpPointer(_dpy, None, _win, None, None, None, None, - (xwa.width / 2), (xwa.height / 2)); - } - // if in normal mouse mode - else - { - // get the relative mouse position - float fX = (float) event.xbutton.x / (float) xwa.width; - float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height; - - // post a normal mouse move event to the event server - server->postEvent (new CEventMouseMove (fX, fY, button, this)); - } break; } case KeyPress: diff --git a/code/nel/src/3d/driver/opengl/unix_event_emitter.h b/code/nel/src/3d/driver/opengl/unix_event_emitter.h index 362ed2086..7eeef970e 100644 --- a/code/nel/src/3d/driver/opengl/unix_event_emitter.h +++ b/code/nel/src/3d/driver/opengl/unix_event_emitter.h @@ -20,7 +20,6 @@ #include "nel/misc/types_nl.h" #include "nel/misc/event_emitter.h" #include "nel/misc/events.h" -#include "nel/misc/game_device_events.h" #include "nel/3d/driver.h" @@ -56,11 +55,6 @@ public: */ virtual void submitEvents(CEventServer & server, bool allWindows); - /** - * enable or disable mouse raw mode - */ - virtual void emulateMouseRawMode(bool emulate); - /** * process input-related events (mouse and keyboard) */ diff --git a/code/nel/src/3d/driver_user.cpp b/code/nel/src/3d/driver_user.cpp index 7ccf4cfce..c4dc97655 100644 --- a/code/nel/src/3d/driver_user.cpp +++ b/code/nel/src/3d/driver_user.cpp @@ -192,8 +192,11 @@ CDriverUser::CDriverUser (uintptr_t windowIcon, TDriver driver, emptyProc exitFu _PBTri.lock (iba); iba.setTri(0, 0, 1, 2); + _RenderTargetManager.m_Driver = this; _ShapeBank._DriverUser = this; + _EffectRenderTarget = NULL; + NL_SET_IB_NAME(_PBLine, "CDriverUser::_PBLine"); NL_SET_IB_NAME(_PBTri, "CDriverUser::_PBTri"); } @@ -246,7 +249,7 @@ bool CDriverUser::setDisplay(nlWindow wnd, const CMode &mode, bool show, bool NL3D_HAUTO_UI_DRIVER; // window init. - if (_Driver->setDisplay(wnd, GfxMode(mode.Width, mode.Height, mode.Depth, mode.Windowed, false, mode.Frequency, mode.AntiAlias), show, resizeable)) + if (_Driver->setDisplay(wnd, GfxMode(mode.Width, mode.Height, mode.Depth, mode.Windowed, false, mode.Frequency, mode.AntiAlias, mode.DisplayDevice), show, resizeable)) { // Always true nlverify (activate()); @@ -290,7 +293,7 @@ bool CDriverUser::setDisplay(nlWindow wnd, const CMode &mode, bool show, bool // *************************************************************************** bool CDriverUser::setMode(const CMode& mode) { - return _Driver->setMode(GfxMode(mode.Width, mode.Height, mode.Depth, mode.Windowed, false, mode.Frequency, mode.AntiAlias)); + return _Driver->setMode(GfxMode(mode.Width, mode.Height, mode.Depth, mode.Windowed, false, mode.Frequency, mode.AntiAlias, mode.DisplayDevice)); } // ---------------------------------------------------------------------------- @@ -316,7 +319,7 @@ bool CDriverUser::getModes(std::vector &modes) bool res = _Driver->getModes(vTmp); modes.clear(); for (uint i = 0; i < vTmp.size(); ++i) - modes.push_back(CMode(vTmp[i].Width, vTmp[i].Height, vTmp[i].Depth, vTmp[i].Windowed, vTmp[i].Frequency, vTmp[i].AntiAlias)); + modes.push_back(CMode(vTmp[i].Width, vTmp[i].Height, vTmp[i].Depth, vTmp[i].Windowed, vTmp[i].Frequency, vTmp[i].AntiAlias, vTmp[i].DisplayDevice)); std::sort(modes.begin(), modes.end(), CModeSorter()); @@ -1357,6 +1360,7 @@ void CDriverUser::swapBuffers() NL3D_HAUTO_SWAP_DRIVER; _Driver->swapBuffers(); + _RenderTargetManager.cleanup(); } // *************************************************************************** @@ -1609,36 +1613,6 @@ bool CDriverUser::fillBuffer (CBitmap &bitmap) // *************************************************************************** // *************************************************************************** -NLMISC::IMouseDevice *CDriverUser::enableLowLevelMouse(bool enable, bool exclusive) -{ - NL3D_HAUTO_UI_DRIVER; - - return _Driver->enableLowLevelMouse(enable, exclusive); -} -NLMISC::IKeyboardDevice *CDriverUser::enableLowLevelKeyboard(bool enable) -{ - NL3D_HAUTO_UI_DRIVER; - - return _Driver->enableLowLevelKeyboard(enable); -} - -void CDriverUser::emulateMouseRawMode(bool enable) -{ - _Driver->getEventEmitter()->emulateMouseRawMode(enable); -} - -uint CDriverUser::getDoubleClickDelay(bool hardwareMouse) -{ - NL3D_HAUTO_UI_DRIVER; - return _Driver->getDoubleClickDelay(hardwareMouse); -} - -NLMISC::IInputDeviceManager *CDriverUser::getLowLevelInputDeviceManager() -{ - NL3D_HAUTO_UI_DRIVER; - - return _Driver->getLowLevelInputDeviceManager(); -} void CDriverUser::showCursor (bool b) { NL3D_HAUTO_UI_DRIVER; @@ -1974,9 +1948,7 @@ bool CDriverUser::setRenderTarget(class UTexture & uTex, uint32 x, uint32 y, uin bool result = _Driver->setRenderTarget(tex, x, y, width, height, mipmapLevel, cubeFace); - CViewport currentViewport; - _Driver->getViewport(currentViewport); - setViewport(currentViewport); + setupMatrixContext(); return result; } diff --git a/code/nel/src/3d/driver_user2.cpp b/code/nel/src/3d/driver_user2.cpp index 990175dd4..1b46ab607 100644 --- a/code/nel/src/3d/driver_user2.cpp +++ b/code/nel/src/3d/driver_user2.cpp @@ -73,6 +73,77 @@ void CDriverUser::deleteScene(UScene *scene) _Scenes.erase((CSceneUser*)scene, "deleteScene(): Bad scene ptr"); } +// *************************************************************************** + +void CDriverUser::beginDefaultRenderTarget(uint32 width, uint32 height) +{ + if (_MatRenderTarget.empty()) + { + _MatRenderTarget.attach(&_MatRenderTargetInt); + UMaterial &umat = _MatRenderTarget; + CMaterial &mat = _MatRenderTargetInt; + umat.initUnlit(); + umat.setColor(CRGBA::White); + umat.setBlend(false); + umat.setAlphaTest(false); + mat.setBlendFunc(CMaterial::one, CMaterial::zero); + mat.setZWrite(false); + mat.setZFunc(CMaterial::always); + mat.setDoubleSided(true); + + _RenderTargetQuad.V0 = CVector(0.f, 0.f, 0.5f); + _RenderTargetQuad.V1 = CVector(1.f, 0.f, 0.5f); + _RenderTargetQuad.V2 = CVector(1.f, 1.f, 0.5f); + _RenderTargetQuad.V3 = CVector(0.f, 1.f, 0.5f); + _RenderTargetQuad.Uv0 = CUV(0.f, 0.f); + _RenderTargetQuad.Uv1 = CUV(1.f, 0.f); + _RenderTargetQuad.Uv2 = CUV(1.f, 1.f); + _RenderTargetQuad.Uv3 = CUV(0.f, 1.f); + } + + nlassert(!_EffectRenderTarget); + if (width == 0 || height == 0) + getWindowSize(width, height); + _EffectRenderTarget = getRenderTargetManager().getRenderTarget(width, height); + setRenderTarget(*_EffectRenderTarget); +} + +// *************************************************************************** + +void CDriverUser::endDefaultRenderTarget(UScene *scene) +{ + nlassert(_EffectRenderTarget); + + CTextureUser texNull; + setRenderTarget(texNull); + + _MatRenderTarget.getObjectPtr()->setTexture(0, _EffectRenderTarget->getITexture()); + + UCamera pCam; + if (scene) + { + pCam = scene->getCam(); + } + CViewport oldVp = getViewport(); + CViewport vp = CViewport(); + setViewport(vp); + setMatrixMode2D11(); + bool fog = fogEnabled(); + enableFog(false); + drawQuad(_RenderTargetQuad, _MatRenderTarget); + enableFog(fog); + setViewport(oldVp); + if (scene) + { + setMatrixMode3D(pCam); + } + + _MatRenderTarget.getObjectPtr()->setTexture(0, NULL); + + getRenderTargetManager().recycleRenderTarget(_EffectRenderTarget); + _EffectRenderTarget = NULL; +} + // *************************************************************************** UTextContext *CDriverUser::createTextContext(const std::string fontFileName, const std::string fontExFileName) { diff --git a/code/nel/src/3d/fxaa.cpp b/code/nel/src/3d/fxaa.cpp new file mode 100644 index 000000000..f19bcd8b4 --- /dev/null +++ b/code/nel/src/3d/fxaa.cpp @@ -0,0 +1,291 @@ +/** + * \file fxaa.cpp + * \brief CFXAA + * \date 2014-08-03 21:41GMT + * \author Jan Boon (Kaetemi) + * CFXAA + */ + +/* + * Copyright (C) 2014 by authors + * + * This file is part of NL3D. + * NL3D is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * NL3D is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with NL3D. If not, see + * . + */ + +#include +#include + +// STL includes + +// NeL includes +// #include + +// Project includes +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +// using namespace NLMISC; + +namespace NL3D { + +namespace { + +#include "fxaa_program.h" + +} /* anonymous namespace */ + +CFXAA::CFXAA(NL3D::UDriver *driver) : m_Driver(driver), m_PP(NULL), m_VP(NULL), m_Width(~0), m_Height(~0) +{ + nldebug("3D: Create FXAA"); + + CDriverUser *dru = static_cast(driver); + NL3D::IDriver *drv = (dru)->getDriver(); + + if (drv->supportBloomEffect() && drv->supportNonPowerOfTwoTextures()) + { + m_PP = new CPixelProgram(); + // arbfp1 + { + IProgram::CSource *source = new IProgram::CSource(); + source->Features.MaterialFlags = CProgramFeatures::TextureStages; + source->Profile = IProgram::arbfp1; + source->setSourcePtr(a_arbfp1); + m_PP->addSource(source); + } + // ps_2_0 + { + IProgram::CSource *source = new IProgram::CSource(); + source->Features.MaterialFlags = CProgramFeatures::TextureStages; + source->Profile = IProgram::ps_2_0; + source->setSourcePtr(a_ps_2_0); + m_PP->addSource(source); + } + if (!drv->compilePixelProgram(m_PP)) + { + nlwarning("3D: No supported pixel program for FXAA effect"); + + delete m_PP; + m_PP = NULL; + } + else + { + nldebug("3D: FXAA pixel program available"); + } + } + + if (!m_PP) + { + return; + } + + // create vp + { + m_VP = new CVertexProgram(); + // nelvp + { + IProgram::CSource *source = new IProgram::CSource(); + source->Features.MaterialFlags = CProgramFeatures::TextureStages; + source->Profile = IProgram::nelvp; + source->setSourcePtr(a_nelvp); + m_VP->addSource(source); + } + if (!drv->compileVertexProgram(m_VP)) + { + nlwarning("3D: No supported vertex program for FXAA effect"); + + delete m_VP; + m_VP = NULL; + delete m_PP; + m_PP = NULL; + } + else + { + nldebug("3D: FXAA vertex program available"); + } + } + + if (!m_VP) + { + return; + } + + // create material and vb + { + m_Mat = m_Driver->createMaterial(); + m_Mat.initUnlit(); + m_Mat.setColor(CRGBA::White); + m_Mat.setBlend (false); + m_Mat.setAlphaTest (false); + NL3D::CMaterial *mat = m_Mat.getObjectPtr(); + mat->setShader(NL3D::CMaterial::Normal); + mat->setBlendFunc(CMaterial::one, CMaterial::zero); + mat->setZWrite(false); + mat->setZFunc(CMaterial::always); + mat->setDoubleSided(true); + + m_QuadUV.V0 = CVector(0.f, 0.f, 0.5f); + m_QuadUV.V1 = CVector(1.f, 0.f, 0.5f); + m_QuadUV.V2 = CVector(1.f, 1.f, 0.5f); + m_QuadUV.V3 = CVector(0.f, 1.f, 0.5f); + + if (drv->textureCoordinateAlternativeMode()) + { + m_QuadUV.Uv0 = CUV(0.f, 1.f); + m_QuadUV.Uv1 = CUV(1.f, 1.f); + m_QuadUV.Uv2 = CUV(1.f, 0.f); + m_QuadUV.Uv3 = CUV(0.f, 0.f); + } + else + { + m_QuadUV.Uv0 = CUV(0.f, 0.f); + m_QuadUV.Uv1 = CUV(1.f, 0.f); + m_QuadUV.Uv2 = CUV(1.f, 1.f); + m_QuadUV.Uv3 = CUV(0.f, 1.f); + } + + /*CVertexBuffer &vb = m_VB; + vb.clearValueEx(); + vb.addValueEx(CVertexBuffer::Position, CVertexBuffer::Float3); + vb.addValueEx(CVertexBuffer::TexCoord0, CVertexBuffer::Float2); + vb.addValueEx(CVertexBuffer::TexCoord1, CVertexBuffer::Float4); + vb.initEx(); + vb.setPreferredMemory(CVertexBuffer::RAMVolatile, false); + vb.setNumVertices(4);*/ + } +} + +CFXAA::~CFXAA() +{ + nldebug("3D: Destroy FXAA"); + + if (!m_Mat.empty()) + { + m_Driver->deleteMaterial(m_Mat); + } + + delete m_VP; + m_VP = NULL; + delete m_PP; + m_PP = NULL; + + m_Driver = NULL; +} + +void CFXAA::applyEffect() +{ + if (!m_PP) + return; + + CDriverUser *dru = static_cast(m_Driver); + IDriver *drv = dru->getDriver(); + + // backup + bool fogEnabled = m_Driver->fogEnabled(); + m_Driver->enableFog(false); + + NL3D::ITexture *renderTarget = drv->getRenderTarget(); + nlassert(renderTarget); + nlassert(renderTarget->isBloomTexture()); + + uint width = renderTarget->getWidth(); + uint height = renderTarget->getHeight(); + bool mode2D = static_cast(renderTarget)->isMode2D(); + nlassert(renderTarget->getUploadFormat() == ITexture::Auto); + + float fwidth = (float)width; + float fheight = (float)height; + float pwidth = 1.0f / fwidth; + float pheight = 1.0f / fheight; + float hpwidth = pwidth * 0.5f; + float hpheight = pheight * 0.5f; + float n = 0.5f; + + //if (width != m_Width || height != m_Height) + /*{ + // Build VB + m_Width = width; + m_Height = height; + CVertexBufferReadWrite vba; + m_VB.lock(vba); + vba.setValueFloat3Ex(CVertexBuffer::Position, 0, 0.f, 0.f, 0.5f); // BL + vba.setValueFloat3Ex(CVertexBuffer::Position, 1, 1.f, 0.f, 0.5f); // BR + vba.setValueFloat3Ex(CVertexBuffer::Position, 2, 1.f, 1.f, 0.5f); // TR + vba.setValueFloat3Ex(CVertexBuffer::Position, 3, 0.f, 1.f, 0.5f); // TL + vba.setValueFloat2Ex(CVertexBuffer::TexCoord0, 0, 0.f, 0.f); + vba.setValueFloat2Ex(CVertexBuffer::TexCoord0, 1, 1.f, 0.f); + vba.setValueFloat2Ex(CVertexBuffer::TexCoord0, 2, 1.f, 1.f); + vba.setValueFloat2Ex(CVertexBuffer::TexCoord0, 3, 0.f, 1.f); + vba.setValueFloat4Ex(CVertexBuffer::TexCoord1, 0, 0.f - hpwidth, 0.f - hpheight, 0.f + hpwidth, 0.f + hpheight); + vba.setValueFloat4Ex(CVertexBuffer::TexCoord1, 1, 1.f - hpwidth, 0.f - hpheight, 1.f + hpwidth, 0.f + hpheight); + vba.setValueFloat4Ex(CVertexBuffer::TexCoord1, 2, 1.f - hpwidth, 1.f - hpheight, 1.f + hpwidth, 1.f + hpheight); + vba.setValueFloat4Ex(CVertexBuffer::TexCoord1, 3, 0.f - hpwidth, 1.f - hpheight, 0.f + hpwidth, 1.f + hpheight); + }*/ + + // create render target + CTextureUser *otherRenderTarget = m_Driver->getRenderTargetManager().getRenderTarget(width, height, mode2D); + + // swap render target + CTextureUser texNull; + dru->setRenderTarget(texNull); + drv->swapTextureHandle(*renderTarget, *otherRenderTarget->getITexture()); + drv->setRenderTarget(renderTarget); + m_Driver->setMatrixMode2D11(); + + // debug + // m_Driver->clearBuffers(CRGBA(128, 128, 128, 128)); + + // activate program + bool vpok = drv->activeVertexProgram(m_VP); + nlassert(vpok); + bool ppok = drv->activePixelProgram(m_PP); + nlassert(ppok); + /*drv->setUniform4f(IDriver::PixelProgram, 0, -n / fwidth, -n / fheight, n / fwidth, n / fheight); // fxaaConsoleRcpFrameOpt + drv->setUniform4f(IDriver::PixelProgram, 1, -2.0f / fwidth, -2.0f / fheight, 2.0f / fwidth, 2.0f / fheight); // fxaaConsoleRcpFrameOpt2*/ + drv->setUniform2f(IDriver::PixelProgram, 0, 1.0f / fwidth, 1.0f / fheight); // fxaaQualityRcpFrame + drv->setUniform1f(IDriver::PixelProgram, 1, 0.75f); // fxaaQualitySubpix + drv->setUniform1f(IDriver::PixelProgram, 2, 0.166f); // fxaaQualityEdgeThreshold + drv->setUniform1f(IDriver::PixelProgram, 3, 0.0833f); // fxaaQualityEdgeThresholdMin + drv->setUniformMatrix(IDriver::VertexProgram, 0, IDriver::ModelViewProjection, IDriver::Identity); + // drv->setUniform4f(IDriver::VertexProgram, 9, -hpwidth, -hpheight, hpwidth, hpheight); + + // render effect + m_Mat.getObjectPtr()->setTexture(0, otherRenderTarget->getITexture()); + /*drv->activeVertexBuffer(m_VB); + drv->renderRawQuads(*m_Mat.getObjectPtr(), 0, 1);*/ + m_Driver->drawQuad(m_QuadUV, m_Mat); + m_Mat.getObjectPtr()->setTexture(0, NULL); + + // deactivate program + drv->activeVertexProgram(NULL); + drv->activePixelProgram(NULL); + + // restore + m_Driver->enableFog(fogEnabled); + + // recycle render target + m_Driver->getRenderTargetManager().recycleRenderTarget(otherRenderTarget); +} + +} /* namespace NL3D */ + +/* end of file */ diff --git a/code/nel/src/3d/fxaa_program.h b/code/nel/src/3d/fxaa_program.h new file mode 100644 index 000000000..a6bf847ef --- /dev/null +++ b/code/nel/src/3d/fxaa_program.h @@ -0,0 +1,994 @@ + +const char *a_nelvp = + "!!VP1.0\n" + "DP4 o[HPOS].x, c[0], v[OPOS];\n" + "DP4 o[HPOS].y, c[1], v[OPOS];\n" + "DP4 o[HPOS].z, c[2], v[OPOS];\n" + "DP4 o[HPOS].w, c[3], v[OPOS];\n" + "MOV o[TEX0].xy, v[TEX0];\n" + // "ADD o[TEX1], v[TEX0].xyxy, c[9];\n" + "END\n"; + +const char *a_arbfp1_test = + "!!ARBfp1.0\n" + "OPTION ARB_precision_hint_fastest;\n" + "TEX result.color, fragment.texcoord[1].zwzw, texture[0], 2D;\n" + "END\n"; + +const char *a_arbfp1 = + "!!ARBfp1.0\n" + "OPTION ARB_precision_hint_fastest;\n" + /*"# cgc version 3.1.0013, build date Apr 18 2012\n" + "# command line args: -profile arbfp1 -O3 -fastmath -fastprecision\n" + "# source file: fxaa_pp.cg\n" + "#vendor NVIDIA Corporation\n" + "#version 3.1.0.13\n" + "#profile arbfp1\n" + "#program fxaa_pp\n" + "#semantic fxaa_pp.fxaaQualityRcpFrame\n" + "#semantic fxaa_pp.fxaaQualitySubpix\n" + "#semantic fxaa_pp.fxaaQualityEdgeThreshold\n" + "#semantic fxaa_pp.fxaaQualityEdgeThresholdMin\n" + "#semantic fxaa_pp.nlTex0 : TEX0\n" + "#var float2 pos : $vin.TEXCOORD0 : TEX0 : 0 : 1\n" + "#var float2 fxaaQualityRcpFrame : : c[0] : 2 : 1\n" + "#var float fxaaQualitySubpix : : c[1] : 3 : 1\n" + "#var float fxaaQualityEdgeThreshold : : c[2] : 4 : 1\n" + "#var float fxaaQualityEdgeThresholdMin : : c[3] : 5 : 1\n" + "#var sampler2D nlTex0 : TEX0 : texunit 0 : 6 : 1\n" + "#var float4 oCol : $vout.COLOR : COL : 7 : 1\n" + "#const c[4] = 0 -1 1 -2\n" + "#const c[5] = 2 0.5 0.25 1.5\n" + "#const c[6] = 4 12 0.083333336 3\n"*/ + "PARAM c[7] = { program.env[0..3],\n" + " { 0, -1, 1, -2 },\n" + " { 2, 0.5, 0.25, 1.5 },\n" + " { 4, 12, 0.083333336, 3 } };\n" + "TEMP R0;\n" + "TEMP R1;\n" + "TEMP R2;\n" + "TEMP R3;\n" + "TEMP R4;\n" + "TEMP R5;\n" + "TEMP R6;\n" + "TEMP R7;\n" + "TEMP R8;\n" + "TEMP R9;\n" + "MOV R3.xyz, c[4];\n" + "MAD R2.zw, R3.xyyz, c[0].xyxy, fragment.texcoord[0].xyxy;\n" + "MAD R0.xy, R3, c[0], fragment.texcoord[0];\n" + "MAD R1.xy, R3.zyzw, c[0], fragment.texcoord[0];\n" + "TEX R5.y, R1, texture[0], 2D;\n" + "MAD R1.xy, R3.zxzw, c[0], fragment.texcoord[0];\n" + "ADD R0.zw, fragment.texcoord[0].xyxy, -c[0].xyxy;\n" + "TEX R4.y, R0.zwzw, texture[0], 2D;\n" + "TEX R6.y, R2.zwzw, texture[0], 2D;\n" + "TEX R8, fragment.texcoord[0], texture[0], 2D;\n" + "TEX R1.y, R1, texture[0], 2D;\n" + "TEX R0.y, R0, texture[0], 2D;\n" + "ADD R0.z, R4.y, R5.y;\n" + "MAD R1.z, R0.y, c[4].w, R0;\n" + "MAD R0.zw, R3.xyyx, c[0].xyxy, fragment.texcoord[0].xyxy;\n" + "TEX R2.y, R0.zwzw, texture[0], 2D;\n" + "ADD R0.x, R2.y, R1.y;\n" + "ABS R0.w, R1.z;\n" + "ADD R1.zw, fragment.texcoord[0].xyxy, c[0].xyxy;\n" + "TEX R7.y, R1.zwzw, texture[0], 2D;\n" + "MAD R0.z, R8.y, c[4].w, R0.x;\n" + "ABS R0.z, R0;\n" + "MAD R2.x, R0.z, c[5], R0.w;\n" + "MAD R0.zw, R3.xyxz, c[0].xyxy, fragment.texcoord[0].xyxy;\n" + "TEX R3.y, R0.zwzw, texture[0], 2D;\n" + "ADD R0.z, R0.y, R3.y;\n" + "ADD R1.x, R6.y, R7.y;\n" + "MAD R0.w, R3.y, c[4], R1.x;\n" + "MAD R1.x, R8.y, c[4].w, R0.z;\n" + "ABS R0.w, R0;\n" + "ADD R2.x, R0.w, R2;\n" + "ADD R2.w, R4.y, R6.y;\n" + "ADD R0.w, R5.y, R7.y;\n" + "ABS R1.z, R1.x;\n" + "MAD R1.x, R1.y, c[4].w, R0.w;\n" + "ABS R1.w, R1.x;\n" + "MAD R1.x, R2.y, c[4].w, R2.w;\n" + "MAD R1.z, R1, c[5].x, R1.w;\n" + "ABS R1.x, R1;\n" + "ADD R1.x, R1, R1.z;\n" + "SGE R4.x, R1, R2;\n" + "MAX R1.x, R3.y, R8.y;\n" + "MAX R1.z, R1.y, R1.x;\n" + "MAX R1.x, R0.y, R2.y;\n" + "MAX R1.x, R1, R1.z;\n" + "MIN R1.z, R3.y, R8.y;\n" + "MIN R1.w, R1.y, R1.z;\n" + "MIN R1.z, R0.y, R2.y;\n" + "MIN R1.z, R1, R1.w;\n" + "MUL R2.x, R1, c[2];\n" + "ADD R3.z, R1.x, -R1;\n" + "ABS R3.w, R4.x;\n" + "MAX R1.w, R2.x, c[3].x;\n" + "ADD R2.z, R3, -R1.w;\n" + "CMP R2.x, R2.z, c[4], c[4].z;\n" + "CMP R1.x, -R3.w, c[4], c[4].z;\n" + "MUL R3.w, R2.x, R1.x;\n" + "CMP R1.z, -R3.w, R1.y, R3.y;\n" + "ADD R1.y, -R8, R1.z;\n" + "CMP R1.w, -R3, R2.y, R0.y;\n" + "ADD R0.y, -R8, R1.w;\n" + "MUL R4.x, R2, R4;\n" + "CMP R3.y, -R3.w, c[0], R3.x;\n" + "ABS R4.w, R1.y;\n" + "ABS R4.z, R0.y;\n" + "SGE R0.y, R4.z, R4.w;\n" + "MUL R1.y, R2.x, R0;\n" + "ABS R0.y, R0;\n" + "CMP R4.y, -R0, c[4].x, c[4].z;\n" + "ABS R0.y, R1.x;\n" + "CMP R0.y, -R0, c[4].x, c[4].z;\n" + "MUL R1.x, R2, R0.y;\n" + "CMP R2.y, -R4.x, c[0], c[0].x;\n" + "CMP R2.y, -R1, -R2, R2;\n" + "MAD R1.y, R2, c[5], fragment.texcoord[0];\n" + "CMP R5.z, -R4.x, R1.y, fragment.texcoord[0].y;\n" + "ADD R5.y, R5.z, -R3;\n" + "MAD R0.y, R2, c[5], fragment.texcoord[0].x;\n" + "CMP R3.x, -R1, c[0], R3;\n" + "CMP R6.x, -R3.w, R0.y, fragment.texcoord[0];\n" + "ADD R5.w, R5.z, R3.y;\n" + "ADD R1.x, R6, -R3;\n" + "MOV R1.y, R5;\n" + "TEX R0.y, R1, texture[0], 2D;\n" + "MUL R1.y, R2.x, R4;\n" + "ADD R0.x, R0.z, R0;\n" + "ADD R0.w, R2, R0;\n" + "MAD R0.z, R0.x, c[5].x, R0.w;\n" + "ADD R1.w, R8.y, R1;\n" + "ADD R1.z, R8.y, R1;\n" + "CMP R4.y, -R1, R1.z, R1.w;\n" + "ADD R1.z, R6.x, R3.x;\n" + "MAD R5.x, -R4.y, c[5].y, R0.y;\n" + "MOV R1.w, R5;\n" + "TEX R0.y, R1.zwzw, texture[0], 2D;\n" + "MAX R1.w, R4.z, R4;\n" + "MAD R1.y, -R4, c[5], R0;\n" + "MUL R4.z, R1.w, c[5];\n" + "ABS R0.y, R1;\n" + "SGE R1.w, R0.y, R4.z;\n" + "ABS R6.y, R5.x;\n" + "SGE R0.y, R6, R4.z;\n" + "ABS R1.w, R1;\n" + "CMP R6.y, -R1.w, c[4].x, c[4].z;\n" + "ABS R0.y, R0;\n" + "CMP R5.z, -R0.y, c[4].x, c[4];\n" + "ADD_SAT R0.y, R5.z, R6;\n" + "MUL R4.w, R2.x, R0.y;\n" + "MUL R0.y, R2.x, R6;\n" + "MAD R1.w, R3.y, c[5], R5;\n" + "CMP R6.x, -R0.y, R1.w, R5.w;\n" + "MAD R6.z, R3.x, c[5].w, R1;\n" + "CMP R1.z, -R0.y, R6, R1;\n" + "MOV R1.w, R6.x;\n" + "TEX R0.y, R1.zwzw, texture[0], 2D;\n" + "MUL R1.w, R4, R6.y;\n" + "CMP R6.y, -R1.w, R0, R1;\n" + "MUL R0.y, R2.x, R5.z;\n" + "MAD R1.y, -R3, c[5].w, R5;\n" + "CMP R5.w, -R0.y, R1.y, R5.y;\n" + "MAD R6.z, -R3.x, c[5].w, R1.x;\n" + "CMP R1.x, -R0.y, R6.z, R1;\n" + "MOV R1.y, R5.w;\n" + "TEX R0.y, R1, texture[0], 2D;\n" + "MUL R5.y, R4.w, R5.z;\n" + "CMP R0.y, -R5, R0, R5.x;\n" + "MAD R5.x, -R4.y, c[5].y, R0.y;\n" + "CMP R5.z, -R5.y, R5.x, R0.y;\n" + "MAD R1.y, -R4, c[5], R6;\n" + "CMP R1.y, -R1.w, R1, R6;\n" + "ABS R1.w, R1.y;\n" + "SGE R1.w, R1, R4.z;\n" + "ABS R0.y, R5.z;\n" + "SGE R0.y, R0, R4.z;\n" + "ABS R1.w, R1;\n" + "CMP R6.y, -R1.w, c[4].x, c[4].z;\n" + "ABS R0.y, R0;\n" + "CMP R5.y, -R0, c[4].x, c[4].z;\n" + "ADD_SAT R0.y, R5, R6;\n" + "MUL R5.x, R4.w, R0.y;\n" + "MUL R0.y, R4.w, R6;\n" + "MAD R1.w, R3.y, c[5].x, R6.x;\n" + "CMP R6.x, -R0.y, R1.w, R6;\n" + "MAD R6.z, R3.x, c[5].x, R1;\n" + "CMP R1.z, -R0.y, R6, R1;\n" + "MOV R1.w, R6.x;\n" + "TEX R0.y, R1.zwzw, texture[0], 2D;\n" + "MUL R1.w, R5.x, R6.y;\n" + "CMP R6.y, -R1.w, R0, R1;\n" + "MUL R0.y, R4.w, R5;\n" + "MAD R1.y, -R3, c[5].x, R5.w;\n" + "CMP R4.w, -R0.y, R1.y, R5;\n" + "MAD R6.z, -R3.x, c[5].x, R1.x;\n" + "CMP R1.x, -R0.y, R6.z, R1;\n" + "MOV R1.y, R4.w;\n" + "TEX R0.y, R1, texture[0], 2D;\n" + "MUL R5.y, R5.x, R5;\n" + "CMP R0.y, -R5, R0, R5.z;\n" + "MAD R5.z, -R4.y, c[5].y, R0.y;\n" + "CMP R5.w, -R5.y, R5.z, R0.y;\n" + "MAD R1.y, -R4, c[5], R6;\n" + "CMP R1.y, -R1.w, R1, R6;\n" + "ABS R1.w, R1.y;\n" + "SGE R1.w, R1, R4.z;\n" + "ABS R1.w, R1;\n" + "CMP R6.y, -R1.w, c[4].x, c[4].z;\n" + "ABS R0.y, R5.w;\n" + "SGE R0.y, R0, R4.z;\n" + "ABS R0.y, R0;\n" + "CMP R5.y, -R0, c[4].x, c[4].z;\n" + "ADD_SAT R0.y, R5, R6;\n" + "MUL R5.z, R5.x, R0.y;\n" + "MUL R0.y, R5.x, R6;\n" + "MAD R1.w, R3.y, c[6].x, R6.x;\n" + "CMP R6.x, -R0.y, R1.w, R6;\n" + "MAD R6.z, R3.x, c[6].x, R1;\n" + "CMP R1.z, -R0.y, R6, R1;\n" + "MOV R1.w, R6.x;\n" + "TEX R0.y, R1.zwzw, texture[0], 2D;\n" + "MUL R1.w, R5.z, R6.y;\n" + "CMP R6.y, -R1.w, R0, R1;\n" + "MUL R0.y, R5.x, R5;\n" + "MAD R1.y, -R3, c[6].x, R4.w;\n" + "CMP R4.w, -R0.y, R1.y, R4;\n" + "MAD R5.x, -R3, c[6], R1;\n" + "CMP R1.x, -R0.y, R5, R1;\n" + "MOV R1.y, R4.w;\n" + "TEX R0.y, R1, texture[0], 2D;\n" + "MUL R1.y, R5.z, R5;\n" + "CMP R5.x, -R1.y, R0.y, R5.w;\n" + "MAD R5.y, -R4, c[5], R5.x;\n" + "CMP R1.y, -R1, R5, R5.x;\n" + "MAD R0.y, -R4, c[5], R6;\n" + "CMP R0.y, -R1.w, R0, R6;\n" + "ABS R5.x, R0.y;\n" + "ABS R1.w, R1.y;\n" + "SGE R1.w, R1, R4.z;\n" + "SGE R5.x, R5, R4.z;\n" + "ABS R4.z, R5.x;\n" + "ABS R1.w, R1;\n" + "CMP R4.z, -R4, c[4].x, c[4];\n" + "CMP R1.w, -R1, c[4].x, c[4].z;\n" + "MUL R4.z, R5, R4;\n" + "MAD R5.y, R3.x, c[6], R1.z;\n" + "CMP R5.y, -R4.z, R5, R1.z;\n" + "MAD R5.x, R3.y, c[6].y, R6;\n" + "CMP R1.z, -R4, R5.x, R6.x;\n" + "MUL R1.w, R5.z, R1;\n" + "ADD R4.z, -fragment.texcoord[0].x, R5.y;\n" + "ADD R1.z, -fragment.texcoord[0].y, R1;\n" + "CMP R1.z, -R3.w, R1, R4;\n" + "MAD R4.z, -R3.x, c[6].y, R1.x;\n" + "MAD R3.x, -R3.y, c[6].y, R4.w;\n" + "CMP R3.y, -R1.w, R4.z, R1.x;\n" + "CMP R1.x, -R1.w, R3, R4.w;\n" + "ADD R1.w, fragment.texcoord[0].x, -R3.y;\n" + "ADD R1.x, fragment.texcoord[0].y, -R1;\n" + "CMP R1.x, -R3.w, R1, R1.w;\n" + "SLT R1.w, R1.x, R1.z;\n" + "ADD R3.x, R1, R1.z;\n" + "ABS R1.w, R1;\n" + "MIN R1.x, R1, R1.z;\n" + "CMP R1.w, -R1, c[4].x, c[4].z;\n" + "MUL R1.z, R2.x, R1.w;\n" + "RCP R3.x, R3.x;\n" + "MAD R1.x, R1, -R3, c[5].y;\n" + "MUL R1.w, R4.y, c[5].y;\n" + "SLT R3.x, R1.y, c[4];\n" + "SLT R1.y, R8, R1.w;\n" + "SLT R0.y, R0, c[4].x;\n" + "ADD R0.y, R0, -R1;\n" + "ADD R1.y, -R1, R3.x;\n" + "ABS R0.y, R0;\n" + "ABS R1.y, R1;\n" + "CMP R0.y, -R0, c[4].z, c[4].x;\n" + "CMP R1.y, -R1, c[4].z, c[4].x;\n" + "CMP R0.x, -R1.z, R0.y, R1.y;\n" + "MAD R0.y, R0.z, c[6].z, -R8;\n" + "ABS R0.x, R0;\n" + "CMP R0.x, -R0, c[4], c[4].z;\n" + "MUL R0.x, R2, R0;\n" + "CMP R0.x, -R0, c[4], R1;\n" + "RCP R0.z, R3.z;\n" + "ABS R0.y, R0;\n" + "MUL_SAT R0.y, R0, R0.z;\n" + "MUL R0.z, R0.y, c[4].w;\n" + "ADD R0.z, R0, c[6].w;\n" + "MUL R0.y, R0, R0;\n" + "MUL R0.y, R0.z, R0;\n" + "MUL R0.y, R0, R0;\n" + "MUL R0.y, R0, c[1].x;\n" + "MAX R0.x, R0, R0.y;\n" + "MAD R0.y, R0.x, R2, fragment.texcoord[0];\n" + "MAD R0.z, R0.x, R2.y, fragment.texcoord[0].x;\n" + "CMP R0.x, -R3.w, R0.z, fragment.texcoord[0];\n" + "CMP R0.y, -R4.x, R0, fragment.texcoord[0];\n" + "TEX R0.xyz, R0, texture[0], 2D;\n" + "CMP R1, R2.z, R8, R9;\n" + "MOV R0.w, R8.y;\n" + "CMP result.color, -R2.x, R0, R1;\n" + "END\n"; + /*"# 260 instructions, 10 R-regs\n" + "\n"*/ + +const char *a_arbfp1_ps3 = + "!!ARBfp1.0\n" + "OPTION ARB_precision_hint_fastest;\n" + //# cgc version 3.1.0013, build date Apr 18 2012 + //# command line args: -profile arbfp1 -O3 -fastmath -fastprecision + //# source file: fxaa_fp.cg + //#vendor NVIDIA Corporation + //#version 3.1.0.13 + //#profile arbfp1 + //#program fxaa_fp + //#semantic fxaa_fp.fxaaConsoleRcpFrameOpt + //#semantic fxaa_fp.fxaaConsoleRcpFrameOpt2 + //#semantic fxaa_fp.nlTex0 : TEX0 + //#var float2 pos : $vin.TEXCOORD0 : TEX0 : 0 : 1 + //#var float4 fxaaConsolePosPos : $vin.TEXCOORD1 : TEX1 : 1 : 1 + //#var float4 fxaaConsoleRcpFrameOpt : : c[0] : 2 : 1 + //#var float4 fxaaConsoleRcpFrameOpt2 : : c[1] : 3 : 1 + //#var sampler2D nlTex0 : TEX0 : texunit 0 : 4 : 1 + //#var float4 oCol : $vout.COLOR : COL : 5 : 1 + //#const c[2] = 0.125 0 -2 2 + //#const c[3] = 0.001953125 0.5 + "PARAM c[4] = { program.env[0..1],\n" + " { 0.125, 0, -2, 2 },\n" + " { 0.001953125, 0.5 } };\n" + "TEMP R0;\n" + "TEMP R1;\n" + "TEMP R2;\n" + "TEMP R3;\n" + "TEMP R4;\n" + "TEMP R5;\n" + "TEX R1.w, fragment.texcoord[1].zyzw, texture[0], 2D;\n" + "ADD R0.x, R1.w, c[3];\n" + "TEX R0.w, fragment.texcoord[1].xwzw, texture[0], 2D;\n" + "TEX R1.w, fragment.texcoord[1], texture[0], 2D;\n" + "ADD R0.y, -R0.x, R0.w;\n" + "ADD R0.z, R1.w, R0.y;\n" + "TEX R2.w, fragment.texcoord[1].zwzw, texture[0], 2D;\n" + "ADD R0.y, -R1.w, R0;\n" + "ADD R1.x, R2.w, R0.y;\n" + "ADD R1.y, R0.z, -R2.w;\n" + "MUL R2.xy, R1, R1;\n" + "ADD R0.y, R2.x, R2;\n" + "RSQ R0.y, R0.y;\n" + "MUL R2.xy, R0.y, R1;\n" + "MAD R3.xy, R2, c[0].zwzw, fragment.texcoord[0];\n" + "ABS R0.z, R2.y;\n" + "ABS R0.y, R2.x;\n" + "MIN R0.y, R0, R0.z;\n" + "RCP R0.y, R0.y;\n" + "MUL R1.xy, R0.y, R2;\n" + "MUL R1.xy, R1, c[2].x;\n" + "MIN R1.xy, R1, c[2].w;\n" + "TEX R4, R3, texture[0], 2D;\n" + "MAD R2.xy, -R2, c[0].zwzw, fragment.texcoord[0];\n" + "TEX R3, R2, texture[0], 2D;\n" + "ADD R3, R3, R4;\n" + "MAX R1.xy, R1, c[2].z;\n" + "MAD R2.xy, R1, c[1].zwzw, fragment.texcoord[0];\n" + "MUL R5, R3, c[3].y;\n" + "MAD R1.xy, -R1, c[1].zwzw, fragment.texcoord[0];\n" + "MIN R0.z, R0.x, R2.w;\n" + "MIN R0.y, R0.w, R1.w;\n" + "MIN R0.y, R0, R0.z;\n" + "MAX R0.z, R0.x, R2.w;\n" + "MAX R0.x, R0.w, R1.w;\n" + "MAX R0.x, R0, R0.z;\n" + "TEX R4, R2, texture[0], 2D;\n" + "TEX R3, R1, texture[0], 2D;\n" + "ADD R3, R3, R4;\n" + "MAD R3, R3, c[3].y, R5;\n" + "MUL R3, R3, c[3].y;\n" + "SLT R0.z, R0.x, R3.w;\n" + "SLT R0.x, R3.w, R0.y;\n" + "ADD_SAT R0.x, R0, R0.z;\n" + "CMP result.color, -R0.x, R5, R3;\n" + "END\n"; + //# 45 instructions, 6 R-regs + +const char *a_arbfp1_earlyexit = + "!!ARBfp1.0\n" + "OPTION ARB_precision_hint_fastest;\n" + //"# cgc version 3.1.0013, build date Apr 18 2012\n" + //"# command line args: -profile arbfp1\n" + //"# source file: fxaa_fp.cg\n" + //"#vendor NVIDIA Corporation\n" + //"#version 3.1.0.13\n" + //"#profile arbfp1\n" + //"#program fxaa_fp\n" + //"#semantic fxaa_fp.fxaaConsoleRcpFrameOpt\n" + //"#semantic fxaa_fp.fxaaConsoleRcpFrameOpt2\n" + //"#semantic fxaa_fp.nlTex0 : TEX0\n" + //"#var float2 pos : $vin.TEXCOORD0 : TEX0 : 0 : 1\n" + //"#var float4 fxaaConsolePosPos : $vin.TEXCOORD1 : TEX1 : 1 : 1\n" + //"#var float4 fxaaConsoleRcpFrameOpt : : c[0] : 2 : 1\n" + //"#var float4 fxaaConsoleRcpFrameOpt2 : : c[1] : 3 : 1\n" + //"#var sampler2D nlTex0 : TEX0 : texunit 0 : 4 : 1\n" + //"#var float4 oCol : $vout.COLOR : COL : 5 : 1\n" + //"#const c[2] = 0.125 0 8 0.001953125\n" + //"#const c[3] = -2 2 0.5\n" + "PARAM c[4] = { program.env[0..1],\n" + " { 0.125, 0, 8, 0.001953125 },\n" + " { -2, 2, 0.5 } };\n" + "TEMP R0;\n" + "TEMP R1;\n" + "TEMP R2;\n" + "TEMP R3;\n" + "TEMP R4;\n" + "TEMP R5;\n" + "TEX R0.w, fragment.texcoord[1].zyzw, texture[0], 2D;\n" + "ADD R0.x, R0.w, c[2].w;\n" + "TEX R1.w, fragment.texcoord[1].xwzw, texture[0], 2D;\n" + "TEX R0.w, fragment.texcoord[1], texture[0], 2D;\n" + "ADD R0.y, R1.w, -R0.x;\n" + "ADD R0.z, R0.w, R0.y;\n" + "TEX R2.w, fragment.texcoord[1].zwzw, texture[0], 2D;\n" + "ADD R0.y, -R0.w, R0;\n" + "ADD R1.z, -R2.w, R0;\n" + "ADD R1.x, R2.w, R0.y;\n" + "MOV R1.y, c[2];\n" + "DP3 R0.y, R1, R1;\n" + "RSQ R0.y, R0.y;\n" + "MUL R2.xy, R0.y, R1.xzzw;\n" + "MAD R3.xy, R2, c[0].zwzw, fragment.texcoord[0];\n" + "ABS R0.z, R2.y;\n" + "ABS R0.y, R2.x;\n" + "MIN R0.y, R0, R0.z;\n" + "RCP R0.y, R0.y;\n" + "MUL R1.xy, R0.y, R2;\n" + "MUL R1.xy, R1, c[2].x;\n" + "MIN R1.xy, R1, c[3].y;\n" + "MIN R0.y, R0.w, R1.w;\n" + "TEX R4, R3, texture[0], 2D;\n" + "MAD R2.xy, -R2, c[0].zwzw, fragment.texcoord[0];\n" + "TEX R3, R2, texture[0], 2D;\n" + "ADD R3, R3, R4;\n" + "MAX R1.xy, R1, c[3].x;\n" + "MAD R2.xy, R1, c[1].zwzw, fragment.texcoord[0];\n" + "MAD R1.xy, -R1, c[1].zwzw, fragment.texcoord[0];\n" + "MUL R5, R3, c[3].z;\n" + "TEX R4, R2, texture[0], 2D;\n" + "TEX R3, R1, texture[0], 2D;\n" + "MIN R0.z, R0.x, R2.w;\n" + "MIN R1.x, R0.y, R0.z;\n" + "MAX R0.y, R0.x, R2.w;\n" + "MAX R0.x, R0.w, R1.w;\n" + "MAX R2.x, R0, R0.y;\n" + "ADD R3, R3, R4;\n" + "MAD R3, R3, c[3].z, R5;\n" + "MUL R3, R3, c[3].z;\n" + "SLT R1.z, R2.x, R3.w;\n" + "SLT R1.y, R3.w, R1.x;\n" + "TEX R0, fragment.texcoord[0], texture[0], 2D;\n" + "ADD_SAT R1.y, R1, R1.z;\n" + "MIN R1.z, R0.w, R1.x;\n" + "MAX R1.x, R2, R0.w;\n" + "ADD R2.y, R1.x, -R1.z;\n" + "CMP R1, -R1.y, R5, R3;\n" + "MAD R2.x, R2.y, c[2].z, -R2;\n" + "CMP result.color, R2.x, R0, R1;\n" + "END\n"; + //"# 51 instructions, 6 R-regs\n" + +const char *a_ps_2_0_test_t0 = + "ps_2_x\n" + "dcl_2d s0\n" + "dcl t0.xyz\n" + "mov r0.xy, t0.xy\n" + "texld r0, r0, s0\n" + "mov oC0, r0\n"; + +const char *a_ps_2_0_test_avg = + "ps_2_x\n" + "dcl_2d s0\n" + "def c0, 0.25000000, 0, 0, 0\n" + "dcl t1\n" + "mov r0.xy, t1.xwzw\n" + "mov r1.xy, t1.zyzw\n" + "texld r0, r0, s0\n" + "texld r1, r1, s0\n" + "add r2, r1, r0\n" + "mov r0.xy, t1.zwzw\n" + "texld r1, t1, s0\n" + "texld r0, r0, s0\n" + "add r1, r2, r1\n" + "add r0, r1, r0\n" + "mul r0, r0, c0.x\n" + "mov oC0, r0\n"; + +const char *a_ps_2_0 = + "ps_2_x\n" + /*"// cgc version 3.1.0013, build date Apr 18 2012\n" + "// command line args: -profile ps_2_x -O3 -fastmath -fastprecision\n" + "// source file: fxaa_pp.cg\n" + "//vendor NVIDIA Corporation\n" + "//version 3.1.0.13\n" + "//profile ps_2_x\n" + "//program fxaa_pp\n" + "//semantic fxaa_pp.fxaaQualityRcpFrame\n" + "//semantic fxaa_pp.fxaaQualitySubpix\n" + "//semantic fxaa_pp.fxaaQualityEdgeThreshold\n" + "//semantic fxaa_pp.fxaaQualityEdgeThresholdMin\n" + "//semantic fxaa_pp.nlTex0 : TEX0\n" + "//var float2 pos : $vin.TEXCOORD0 : TEX0 : 0 : 1\n" + "//var float2 fxaaQualityRcpFrame : : c[0] : 2 : 1\n" + "//var float fxaaQualitySubpix : : c[1] : 3 : 1\n" + "//var float fxaaQualityEdgeThreshold : : c[2] : 4 : 1\n" + "//var float fxaaQualityEdgeThresholdMin : : c[3] : 5 : 1\n" + "//var sampler2D nlTex0 : TEX0 : texunit 0 : 6 : 1\n" + "//var float4 oCol : $vout.COLOR : COL : 7 : 1\n" + "//const c[4] = 0 -1 1 -2\n" + "//const c[5] = 2 0.5 0.25 1.5\n" + "//const c[6] = 4 12 0.083333336\n" + "//const c[7] = -2 3\n"*/ + "dcl_2d s0\n" + "def c4, 0.00000000, -1.00000000, 1.00000000, -2.00000000\n" + "def c5, 2.00000000, 0.50000000, 0.25000000, 1.50000000\n" + "def c6, 4.00000000, 12.00000000, 0.08333334, 0\n" + "def c7, -2.00000000, 3.00000000, 0, 0\n" + "dcl t0.xy\n" + "mov r0.zw, c0.xyxy\n" + "mad r3.xy, c4.zxzw, r0.zwzw, t0\n" + "texld r7, r3, s0\n" + "texld r1, t0, s0\n" + "mov r0.xy, c0\n" + "mad r0.xy, c4.yxzw, r0, t0\n" + "texld r8, r0, s0\n" + "mov r0.xy, c0\n" + "mad r0.xy, c4, r0, t0\n" + "texld r9, r0, s0\n" + "add r0.xy, t0, -c0\n" + "texld r5, r0, s0\n" + "mov r3.xy, c0\n" + "mad r3.xy, c4.zyzw, r3, t0\n" + "texld r3, r3, s0\n" + "add r7.x, r8.y, r7.y\n" + "mad r0.z, r1.y, c4.w, r7.x\n" + "add r0.x, r5.y, r3.y\n" + "mad r0.w, r9.y, c4, r0.x\n" + "mov r0.xy, c0\n" + "mad r0.xy, c4.xzzw, r0, t0\n" + "texld r6, r0, s0\n" + "add r5.x, r9.y, r6.y\n" + "abs r0.z, r0\n" + "abs r0.w, r0\n" + "mad r3.x, r0.z, c5, r0.w\n" + "mov r0.zw, c0.xyxy\n" + "mad r4.xy, c4.yzzw, r0.zwzw, t0\n" + "texld r4, r4, s0\n" + "add r0.xy, t0, c0\n" + "texld r0, r0, s0\n" + "add r4.x, r5.y, r4.y\n" + "add r5.y, r3, r0\n" + "add r0.x, r4.y, r0.y\n" + "mad r0.x, r6.y, c4.w, r0\n" + "abs r0.x, r0\n" + "add r0.w, r0.x, r3.x\n" + "mad r0.x, r8.y, c4.w, r4\n" + "mad r0.z, r7.y, c4.w, r5.y\n" + "mad r0.y, r1, c4.w, r5.x\n" + "abs r0.z, r0\n" + "abs r0.y, r0\n" + "mad r0.y, r0, c5.x, r0.z\n" + "abs r0.x, r0\n" + "add r0.x, r0, r0.y\n" + "add r0.x, r0, -r0.w\n" + "cmp r3.y, r0.x, c4.z, c4.x\n" + "max r0.y, r6, r1\n" + "max r0.z, r7.y, r0.y\n" + "max r0.y, r9, r8\n" + "max r0.y, r0, r0.z\n" + "min r0.z, r6.y, r1.y\n" + "min r0.w, r7.y, r0.z\n" + "min r0.z, r9.y, r8.y\n" + "min r0.z, r0, r0.w\n" + "mul r3.x, r0.y, c2\n" + "abs_pp r0.x, r3.y\n" + "add r4.y, r0, -r0.z\n" + "max r0.w, r3.x, c3.x\n" + "add r4.z, r4.y, -r0.w\n" + "cmp_pp r4.w, r4.z, c4.z, c4.x\n" + "mul_pp r5.w, r4, r3.y\n" + "cmp_pp r0.y, -r0.x, c4.z, c4.x\n" + "mul_pp r5.z, r4.w, r0.y\n" + "cmp_pp r3.x, -r0, c4, c4.z\n" + "cmp r6.w, -r5.z, r6.y, r7.y\n" + "cmp r7.w, -r5.z, r9.y, r8.y\n" + "add r0.z, -r1.y, r6.w\n" + "add r0.y, -r1, r7.w\n" + "abs r9.z, r0\n" + "abs r7.y, r0\n" + "add r0.y, r7, -r9.z\n" + "cmp r0.y, r0, c4.z, c4.x\n" + "max r7.y, r7, r9.z\n" + "mul_pp r0.z, r4.w, r0.y\n" + "cmp r0.w, -r5, c0.x, c0.y\n" + "cmp r6.x, -r0.z, r0.w, -r0.w\n" + "mov r0.z, c0.y\n" + "cmp r6.y, -r5.z, c4.x, r0.z\n" + "mad r0.w, r6.x, c5.y, t0.y\n" + "cmp r0.z, -r5.w, t0.y, r0.w\n" + "add r8.z, r0, r6.y\n" + "add r7.z, r0, -r6.y\n" + "mov r9.y, r7.z\n" + "mov r8.y, r8.z\n" + "mad r0.w, r6.x, c5.y, t0.x\n" + "mov r0.x, c0\n" + "mul_pp r3.x, r4.w, r3\n" + "cmp r6.z, -r3.x, c4.x, r0.x\n" + "cmp r0.x, -r5.z, t0, r0.w\n" + "add r9.x, r0, -r6.z\n" + "texld r3, r9, s0\n" + "add r8.x, r0, r6.z\n" + "abs_pp r3.x, r0.y\n" + "texld r0, r8, s0\n" + "cmp_pp r0.x, -r3, c4.z, c4\n" + "add r0.w, r1.y, r6\n" + "add r0.z, r1.y, r7.w\n" + "mul_pp r0.x, r4.w, r0\n" + "cmp r6.w, -r0.x, r0.z, r0\n" + "mad r7.w, -r6, c5.y, r0.y\n" + "mad r8.w, -r6, c5.y, r3.y\n" + "abs r0.y, r7.w\n" + "abs r0.x, r8.w\n" + "mad r0.x, -r7.y, c5.z, r0\n" + "mad r0.y, -r7, c5.z, r0\n" + "cmp r0.x, r0, c4.z, c4\n" + "abs_pp r0.x, r0\n" + "cmp_pp r9.z, -r0.x, c4, c4.x\n" + "cmp r0.y, r0, c4.z, c4.x\n" + "abs_pp r0.y, r0\n" + "cmp_pp r9.w, -r0.y, c4.z, c4.x\n" + "mul_pp r0.x, r4.w, r9.z\n" + "mad r0.y, -r6, c5.w, r7.z\n" + "cmp r7.z, -r0.x, r7, r0.y\n" + "mad r0.z, -r6, c5.w, r9.x\n" + "cmp r9.x, -r0, r9, r0.z\n" + "mov r9.y, r7.z\n" + "texld r3, r9, s0\n" + "add_pp_sat r3.z, r9, r9.w\n" + "mul_pp r0.x, r4.w, r9.w\n" + "mad r0.y, r6, c5.w, r8.z\n" + "cmp r3.x, -r0, r8.z, r0.y\n" + "mad r0.z, r6, c5.w, r8.x\n" + "mul_pp r8.z, r4.w, r3\n" + "cmp r8.x, -r0, r8, r0.z\n" + "mov r8.y, r3.x\n" + "texld r0, r8, s0\n" + "mul_pp r0.w, r8.z, r9\n" + "cmp r3.z, -r0.w, r7.w, r0.y\n" + "mul_pp r0.x, r8.z, r9.z\n" + "cmp r0.y, -r0.x, r8.w, r3\n" + "mad r0.z, -r6.w, c5.y, r0.y\n" + "cmp r8.w, -r0.x, r0.y, r0.z\n" + "mad r3.y, -r6.w, c5, r3.z\n" + "cmp r9.w, -r0, r3.z, r3.y\n" + "abs r0.y, r9.w\n" + "abs r0.x, r8.w\n" + "mad r0.y, -r7, c5.z, r0\n" + "mad r0.x, -r7.y, c5.z, r0\n" + "cmp r0.y, r0, c4.z, c4.x\n" + "abs_pp r0.y, r0\n" + "cmp_pp r10.x, -r0.y, c4.z, c4\n" + "cmp r0.x, r0, c4.z, c4\n" + "abs_pp r0.x, r0\n" + "cmp_pp r9.z, -r0.x, c4, c4.x\n" + "mul_pp r0.x, r8.z, r10\n" + "mad r0.y, r6, c5.x, r3.x\n" + "cmp r7.w, -r0.x, r3.x, r0.y\n" + "mad r0.z, r6, c5.x, r8.x\n" + "cmp r8.x, -r0, r8, r0.z\n" + "mov r8.y, r7.w\n" + "texld r0, r8, s0\n" + "mul_pp r0.w, r8.z, r9.z\n" + "mad r3.x, -r6.z, c5, r9\n" + "mad r0.x, -r6.y, c5, r7.z\n" + "cmp r0.x, -r0.w, r7.z, r0\n" + "add_pp_sat r0.z, r9, r10.x\n" + "mul_pp r7.z, r8, r0\n" + "cmp r9.x, -r0.w, r9, r3\n" + "mov r9.y, r0.x\n" + "texld r3, r9, s0\n" + "mul_pp r0.z, r7, r9\n" + "cmp r0.w, -r0.z, r8, r3.y\n" + "mul_pp r3.x, r7.z, r10\n" + "cmp r3.y, -r3.x, r9.w, r0\n" + "mad r0.y, -r6.w, c5, r0.w\n" + "cmp r8.z, -r0, r0.w, r0.y\n" + "mad r3.z, -r6.w, c5.y, r3.y\n" + "cmp r9.z, -r3.x, r3.y, r3\n" + "abs r0.y, r8.z\n" + "abs r0.z, r9\n" + "mad r0.y, -r7, c5.z, r0\n" + "mad r0.z, -r7.y, c5, r0\n" + "cmp r0.y, r0, c4.z, c4.x\n" + "abs_pp r0.y, r0\n" + "cmp_pp r8.w, -r0.y, c4.z, c4.x\n" + "cmp r0.z, r0, c4, c4.x\n" + "abs_pp r0.z, r0\n" + "cmp_pp r9.w, -r0.z, c4.z, c4.x\n" + "mul_pp r0.y, r7.z, r8.w\n" + "mad r0.z, -r6.y, c6.x, r0.x\n" + "cmp r10.x, -r0.y, r0, r0.z\n" + "mad r0.w, -r6.z, c6.x, r9.x\n" + "cmp r9.x, -r0.y, r9, r0.w\n" + "mov r9.y, r10.x\n" + "texld r3, r9, s0\n" + "mul_pp r0.x, r7.z, r9.w\n" + "mad r0.z, r6, c6.x, r8.x\n" + "mad r0.y, r6, c6.x, r7.w\n" + "cmp r3.x, -r0, r7.w, r0.y\n" + "cmp r8.x, -r0, r8, r0.z\n" + "mov r8.y, r3.x\n" + "texld r0, r8, s0\n" + "add_pp_sat r3.z, r8.w, r9.w\n" + "mul_pp r0.x, r7.z, r3.z\n" + "mul_pp r3.z, r0.x, r9.w\n" + "cmp r0.y, -r3.z, r9.z, r0\n" + "mul_pp r0.z, r0.x, r8.w\n" + "cmp r0.w, -r0.z, r8.z, r3.y\n" + "mad r3.w, -r6, c5.y, r0.y\n" + "cmp r0.y, -r3.z, r0, r3.w\n" + "mad r3.y, -r6.w, c5, r0.w\n" + "cmp r0.z, -r0, r0.w, r3.y\n" + "abs r3.y, r0\n" + "abs r0.w, r0.z\n" + "mad r3.y, -r7, c5.z, r3\n" + "mad r0.w, -r7.y, c5.z, r0\n" + "cmp r3.y, r3, c4.z, c4.x\n" + "abs_pp r3.y, r3\n" + "cmp r0.w, r0, c4.z, c4.x\n" + "cmp_pp r3.z, -r3.y, c4, c4.x\n" + "abs_pp r0.w, r0\n" + "cmp_pp r3.y, -r0.w, c4.z, c4.x\n" + "mul_pp r0.w, r0.x, r3.z\n" + "mul_pp r0.x, r0, r3.y\n" + "mad r3.w, r6.y, c6.y, r3.x\n" + "cmp r3.x, -r0.w, r3, r3.w\n" + "mad r3.z, r6, c6.y, r8.x\n" + "cmp r0.w, -r0, r8.x, r3.z\n" + "mad r3.y, -r6, c6, r10.x\n" + "cmp r3.y, -r0.x, r10.x, r3\n" + "add r3.x, -t0.y, r3\n" + "add r0.w, -t0.x, r0\n" + "cmp r0.w, -r5.z, r0, r3.x\n" + "mad r3.x, -r6.z, c6.y, r9\n" + "cmp r0.x, -r0, r9, r3\n" + "add r3.x, t0.y, -r3.y\n" + "add r0.x, t0, -r0\n" + "cmp r0.x, -r5.z, r0, r3\n" + "add r3.x, r0, -r0.w\n" + "add r3.y, r0.x, r0.w\n" + "cmp r3.x, r3, c4, c4.z\n" + "abs_pp r3.x, r3\n" + "min r0.x, r0, r0.w\n" + "cmp_pp r3.x, -r3, c4.z, c4\n" + "mul_pp r0.w, r4, r3.x\n" + "rcp r3.y, r3.y\n" + "mad r0.x, r0, -r3.y, c5.y\n" + "cmp r3.y, r0, c4.x, c4.z\n" + "mad r3.x, -r6.w, c5.y, r1.y\n" + "cmp r3.x, r3, c4, c4.z\n" + "cmp r0.y, r0.z, c4.x, c4.z\n" + "add_pp r0.z, -r3.x, r3.y\n" + "add_pp r0.y, r0, -r3.x\n" + "abs_pp r0.y, r0\n" + "abs_pp r0.z, r0\n" + "cmp_pp r0.z, -r0, c4.x, c4\n" + "cmp_pp r0.y, -r0, c4.x, c4.z\n" + "cmp_pp r0.y, -r0.w, r0, r0.z\n" + "abs_pp r0.y, r0\n" + "cmp_pp r0.y, -r0, c4.z, c4.x\n" + "mul_pp r0.y, r4.w, r0\n" + "rcp r0.w, r4.y\n" + "cmp r0.x, -r0.y, r0, c4\n" + "add r3.y, r4.x, r5\n" + "add r3.x, r5, r7\n" + "mad r3.x, r3, c5, r3.y\n" + "mad r0.z, r3.x, c6, -r1.y\n" + "abs r0.z, r0\n" + "mul_sat r0.z, r0, r0.w\n" + "mul r0.w, r0.z, r0.z\n" + "mad r0.z, r0, c7.x, c7.y\n" + "mul r0.z, r0, r0.w\n" + "mul r0.z, r0, r0\n" + "mul r0.z, r0, c1.x\n" + "max r0.x, r0, r0.z\n" + "mad r0.y, r0.x, r6.x, t0\n" + "mad r0.z, r0.x, r6.x, t0.x\n" + "cmp r0.x, -r5.z, t0, r0.z\n" + "cmp r0.y, -r5.w, t0, r0\n" + "texld r0, r0, s0\n" + "mov r0.w, r1.y\n" + "cmp r1, r4.z, r2, r1\n" + "cmp r0, -r4.w, r1, r0\n" + "mov oC0, r0\n"; + +const char *a_ps_2_0_ps3 = + "ps_2_0\n" + // cgc version 3.1.0013, build date Apr 18 2012 + // command line args: -profile ps_2_0 -O3 -fastmath -fastprecision + // source file: fxaa_pp.cg + //vendor NVIDIA Corporation + //version 3.1.0.13 + //profile ps_2_0 + //program fxaa_pp + //semantic fxaa_pp.fxaaConsoleRcpFrameOpt + //semantic fxaa_pp.fxaaConsoleRcpFrameOpt2 + //semantic fxaa_pp.nlTex0 : TEX0 + //var float2 pos : $vin.TEXCOORD0 : TEX0 : 0 : 1 + //var float4 fxaaConsolePosPos : $vin.TEXCOORD1 : TEX1 : 1 : 1 + //var float4 fxaaConsoleRcpFrameOpt : : c[0] : 2 : 1 + //var float4 fxaaConsoleRcpFrameOpt2 : : c[1] : 3 : 1 + //var sampler2D nlTex0 : TEX0 : texunit 0 : 4 : 1 + //var float4 oCol : $vout.COLOR : COL : 5 : 1 + //const c[2] = 0.001953125 0.125 2 -2 + //const c[3] = 0.5 0 1 + "dcl_2d s0\n" + "def c2, 0.00195313, 0.12500000, 2.00000000, -2.00000000\n" + "def c3, 0.50000000, 0.00000000, 1.00000000, 0\n" + "dcl t1\n" + "dcl t0.xy\n" + "texld r5, t1, s0\n" + "mov r1.y, t1.w\n" + "mov r1.x, t1.z\n" + "mov r2.xy, r1\n" + "mov r0.y, t1.w\n" + "mov r0.x, t1\n" + "mov r1.y, t1\n" + "mov r1.x, t1.z\n" + "texld r1, r1, s0\n" + "texld r0, r0, s0\n" + "texld r6, r2, s0\n" + "add r0.x, r1.w, c2\n" + "add r2.x, -r0, r0.w\n" + "add r1.x, r5.w, r2\n" + "add r2.z, r1.x, -r6.w\n" + "add r2.x, -r5.w, r2\n" + "add r2.x, r6.w, r2\n" + "mov r3.x, r2\n" + "mov r3.y, r2.z\n" + "mov r2.y, r2.z\n" + "mov r1.y, r2.z\n" + "mov r1.x, r2\n" + "mul r1.xy, r3, r1\n" + "add r1.x, r1, r1.y\n" + "rsq r1.x, r1.x\n" + "mul r4.xy, r1.x, r2\n" + "abs r2.x, r4.y\n" + "abs r1.x, r4\n" + "min r1.x, r1, r2\n" + "rcp r1.x, r1.x\n" + "mul r1.xy, r1.x, r4\n" + "mul r1.xy, r1, c2.y\n" + "min r1.xy, r1, c2.z\n" + "max r2.xy, r1, c2.w\n" + "mov r1.y, c1.w\n" + "mov r1.x, c1.z\n" + "mad r3.xy, r2, r1, t0\n" + "mov r1.y, c1.w\n" + "mov r1.x, c1.z\n" + "mad r5.xy, -r2, r1, t0\n" + "mov r1.y, c0.w\n" + "mov r1.x, c0.z\n" + "mad r2.xy, -r4, r1, t0\n" + "mov r1.y, c0.w\n" + "mov r1.x, c0.z\n" + "mad r1.xy, r4, r1, t0\n" + "texld r4, r5, s0\n" + "texld r3, r3, s0\n" + "texld r1, r1, s0\n" + "texld r2, r2, s0\n" + "add r1, r2, r1\n" + "mul r2, r1, c3.x\n" + "add r1, r4, r3\n" + "max r3.x, r0, r6.w\n" + "mad r1, r1, c3.x, r2\n" + "mul r4, r1, c3.x\n" + "max r1.x, r0.w, r5.w\n" + "max r1.x, r1, r3\n" + "add r1.x, -r4.w, r1\n" + "min r3.x, r0.w, r5.w\n" + "min r0.x, r0, r6.w\n" + "min r0.x, r3, r0\n" + "add r0.x, r4.w, -r0\n" + "cmp r1.x, r1, c3.y, c3.z\n" + "cmp r0.x, r0, c3.y, c3.z\n" + "add_pp_sat r0.x, r0, r1\n" + "cmp r0, -r0.x, r4, r2\n" + "mov oC0, r0\n"; + +const char *a_ps_2_0_earlyexit = + "ps_2_x\n" + // cgc version 3.1.0013, build date Apr 18 2012 + // command line args: -profile ps_2_x + // source file: fxaa_fp.cg + //vendor NVIDIA Corporation + //version 3.1.0.13 + //profile ps_2_x + //program fxaa_fp + //semantic fxaa_fp.fxaaConsoleRcpFrameOpt + //semantic fxaa_fp.fxaaConsoleRcpFrameOpt2 + //semantic fxaa_fp.nlTex0 : TEX0 + //var float2 pos : $vin.TEXCOORD0 : TEX0 : 0 : 1 + //var float4 fxaaConsolePosPos : $vin.TEXCOORD1 : TEX1 : 1 : 1 + //var float4 fxaaConsoleRcpFrameOpt : : c[0] : 2 : 1 + //var float4 fxaaConsoleRcpFrameOpt2 : : c[1] : 3 : 1 + //var sampler2D nlTex0 : TEX0 : texunit 0 : 4 : 1 + //var float4 oCol : $vout.COLOR : COL : 5 : 1 + //const c[2] = 0.001953125 0 0.125 2 + //const c[3] = -2 0.5 0 1 + //const c[4] = 8 + "dcl_2d s0\n" + "def c2, 0.00195313, 0.00000000, 0.12500000, 2.00000000\n" + "def c3, -2.00000000, 0.50000000, 0.00000000, 1.00000000\n" + "def c4, 8.00000000, 0, 0, 0\n" + "dcl t1\n" + "dcl t0.xy\n" + "mov r0.xy, t1.zyzw\n" + "texld r0, r0, s0\n" + "mov r0.xy, t1.xwzw\n" + "texld r5, t1, s0\n" + "texld r4, r0, s0\n" + "add r4.x, r0.w, c2\n" + "mov r0.xy, t1.zwzw\n" + "texld r3, r0, s0\n" + "add r0.w, r4, -r4.x\n" + "add r0.x, r5.w, r0.w\n" + "add r0.z, -r3.w, r0.x\n" + "add r0.x, -r5.w, r0.w\n" + "add r0.x, r3.w, r0\n" + "mov r0.y, c2\n" + "dp3 r0.y, r0, r0\n" + "rsq r0.y, r0.y\n" + "mul r0.zw, r0.y, r0.xyxz\n" + "mad r1.xy, -r0.zwzw, c0.zwzw, t0\n" + "texld r1, r1, s0\n" + "abs r0.y, r0.w\n" + "abs r0.x, r0.z\n" + "min r0.x, r0, r0.y\n" + "rcp r0.x, r0.x\n" + "mul r0.xy, r0.x, r0.zwzw\n" + "mul r0.xy, r0, c2.z\n" + "min r2.xy, r0, c2.w\n" + "mad r0.xy, r0.zwzw, c0.zwzw, t0\n" + "texld r0, r0, s0\n" + "add r0, r1, r0\n" + "max r1.xy, r2, c3.x\n" + "mul r2, r0, c3.y\n" + "mad r0.xy, r1, c1.zwzw, t0\n" + "mad r1.xy, -r1, c1.zwzw, t0\n" + "texld r0, r0, s0\n" + "texld r1, r1, s0\n" + "add r0, r1, r0\n" + "mad r0, r0, c3.y, r2\n" + "mul r1, r0, c3.y\n" + "min r0.y, r4.x, r3.w\n" + "min r0.x, r5.w, r4.w\n" + "min r3.y, r0.x, r0\n" + "add r0.x, -r3.y, r1.w\n" + "max r0.z, r4.x, r3.w\n" + "max r0.y, r5.w, r4.w\n" + "max r3.x, r0.y, r0.z\n" + "cmp r3.z, r0.x, c3, c3.w\n" + "add r3.w, r3.x, -r1\n" + "cmp r3.w, r3, c3.z, c3\n" + "add_pp_sat r3.z, r3, r3.w\n" + "texld r0, t0, s0\n" + "min r3.w, r0, r3.y\n" + "max r3.y, r3.x, r0.w\n" + "cmp r1, -r3.z, r1, r2\n" + "add r3.y, r3, -r3.w\n" + "mad r2.x, r3.y, c4, -r3\n" + "cmp r0, r2.x, r1, r0\n" + "mov oC0, r0\n"; diff --git a/code/nel/src/3d/particle_system.cpp b/code/nel/src/3d/particle_system.cpp index 3b25c3e1e..f6060640b 100644 --- a/code/nel/src/3d/particle_system.cpp +++ b/code/nel/src/3d/particle_system.cpp @@ -422,6 +422,11 @@ void CParticleSystem::step(TPass pass, TAnimationTime ellapsedTime, CParticleSys NL_PS_FUNC_MAIN(CParticleSystem_step) CHECK_INTEGRITY OwnerModel = &model; + if (!_CoordSystemInfo.Matrix) + { + nlwarning("3D: BUG: CParticleSystem::step -> !_CoordSystemInfo.Matrix"); + return; + } nlassert(_CoordSystemInfo.Matrix); // matrix not set for position of system if (_UserCoordSystemInfo) { diff --git a/code/nel/src/3d/render_target_manager.cpp b/code/nel/src/3d/render_target_manager.cpp new file mode 100644 index 000000000..0c4daa507 --- /dev/null +++ b/code/nel/src/3d/render_target_manager.cpp @@ -0,0 +1,162 @@ +/** + * \file render_target_manager.cpp + * \brief CRenderTargetManager + * \date 2014-07-30 21:30GMT + * \author Jan Boon (Kaetemi) + * CRenderTargetManager + */ + +/* + * Copyright (C) 2014 by authors + * + * This file is part of NL3D. + * NL3D is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * NL3D is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with NL3D. If not, see + * . + */ + +#include +#include + +// STL includes +#include + +// NeL includes +// #include +#include +#include +#include +#include +#include +#include +#include + +// Project includes + +using namespace std; +// using namespace NLMISC; + +namespace NL3D { + +struct CRenderTargetDescInt +{ +public: + // Options + uint Width; + uint Height; + bool Mode2D; + UTexture::TUploadFormat Format; + + // Data + NL3D::CTextureUser *TextureUser; + NLMISC::CSmartPtr TextureInterface; + bool InUse; + bool Used; +}; + +CRenderTargetManager::CRenderTargetManager() : m_Driver(NULL) +{ + +} + +CRenderTargetManager::~CRenderTargetManager() +{ + // Call twice to reset counters and cleanup + cleanup(); + cleanup(); +} + +NL3D::CTextureUser *CRenderTargetManager::getRenderTarget(uint width, uint height, bool mode2D, UTexture::TUploadFormat format) +{ + // Find or create a render target, short loop so no real optimization + for (std::vector::iterator it(m_RenderTargets.begin()), end(m_RenderTargets.end()); it != end; ++it) + { + CRenderTargetDescInt *desc = *it; + if (!desc->InUse && desc->Width == width && desc->Height == height && desc->Mode2D == mode2D && desc->Format == format) + { + desc->InUse = true; + desc->Used = true; + return desc->TextureUser; + } + } + + nldebug("3D: Create new render target (%u x %u)", width, height); + NL3D::IDriver *drvInternal = (static_cast(m_Driver))->getDriver(); + CRenderTargetDescInt *desc = new CRenderTargetDescInt(); + CTextureBloom *tex = new CTextureBloom(); // LOL + tex->mode2D(mode2D); + desc->TextureInterface = tex; + desc->TextureInterface->setRenderTarget(true); + desc->TextureInterface->setReleasable(false); + desc->TextureInterface->setUploadFormat((ITexture::TUploadFormat)(uint32)format); + desc->TextureInterface->resize(width, height); + desc->TextureInterface->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff); + desc->TextureInterface->setWrapS(ITexture::Clamp); + desc->TextureInterface->setWrapT(ITexture::Clamp); + drvInternal->setupTexture(*desc->TextureInterface); + desc->TextureUser = new CTextureUser(desc->TextureInterface); + nlassert(!drvInternal->isTextureRectangle(desc->TextureInterface)); // Not allowed, we only support NPOT for render targets now. + desc->Width = width; + desc->Height = height; + desc->Mode2D = mode2D; + desc->Format = format; + desc->Used = true; + desc->InUse = true; + m_RenderTargets.push_back(desc); + return desc->TextureUser; +} + +void CRenderTargetManager::recycleRenderTarget(NL3D::CTextureUser *renderTarget) +{ + for (std::vector::iterator it(m_RenderTargets.begin()), end(m_RenderTargets.end()); it != end; ++it) + { + CRenderTargetDescInt *desc = *it; + if (desc->TextureUser == renderTarget) + { + desc->InUse = false; + return; + } + } + nlerror("3D: Render target not found"); +} + +void CRenderTargetManager::cleanup() +{ + for (sint i = 0; i < (sint)m_RenderTargets.size(); ++i) + { + CRenderTargetDescInt *desc = m_RenderTargets[i]; + nlassert(!desc->InUse); // Assert for debugging, to not allow textures being carried over between frames. Optional assert + if (!desc->InUse) + { + if (!desc->Used) + { + // No longer in use + nldebug("3D: Release render target (%u x %u)", desc->Width, desc->Height); + delete desc->TextureUser; + desc->TextureUser = NULL; + desc->TextureInterface = NULL; // CSmartPtr + m_RenderTargets.erase(m_RenderTargets.begin() + i); + --i; + } + else + { + // Flag for next round + desc->Used = false; + } + } + } +} + +} /* namespace NL3D */ + +/* end of file */ diff --git a/code/nel/src/3d/render_trav.cpp b/code/nel/src/3d/render_trav.cpp index e7dfe89b1..026e80e9c 100644 --- a/code/nel/src/3d/render_trav.cpp +++ b/code/nel/src/3d/render_trav.cpp @@ -92,7 +92,7 @@ CRenderTrav::CRenderTrav() // *************************************************************************** -void CRenderTrav::traverse(UScene::TRenderPart renderPart, bool newRender) +void CRenderTrav::traverse(UScene::TRenderPart renderPart, bool newRender, bool generateShadows) { #ifdef NL_DEBUG_RENDER_TRAV nlwarning("Render trave begin"); @@ -279,7 +279,8 @@ void CRenderTrav::traverse(UScene::TRenderPart renderPart, bool newRender) */ // Generate ShadowMaps - _ShadowMapManager.renderGenerate(Scene); + if (generateShadows) + _ShadowMapManager.renderGenerate(Scene); // Render the Landscape renderLandscapes(); diff --git a/code/nel/src/3d/scene.cpp b/code/nel/src/3d/scene.cpp index fb2d476ac..67465eb8c 100644 --- a/code/nel/src/3d/scene.cpp +++ b/code/nel/src/3d/scene.cpp @@ -353,28 +353,31 @@ void CScene::beginPartRender() // *************************************************************************** -void CScene::endPartRender() +void CScene::endPartRender(bool keepTrav) { nlassert(_IsRendering); - - // Delete model deleted during the rendering _IsRendering = false; - uint i; - for (i=0; i<_ToDelete.size(); i++) - deleteModel (_ToDelete[i]); - _ToDelete.clear (); - // Special for SkeletonSpawnScript animation. create models spawned now - flushSSSModelRequests(); + if (!keepTrav) + { + // Delete model deleted during the rendering + uint i; + for (i=0; i<_ToDelete.size(); i++) + deleteModel (_ToDelete[i]); + _ToDelete.clear (); - // Particle system handling (remove the resources of those which are too far, as their clusters may not have been parsed). - // Note that only a few of them are tested at each call - _ParticleSystemManager.refreshModels(ClipTrav.WorldFrustumPyramid, ClipTrav.CamPos); + // Special for SkeletonSpawnScript animation. create models spawned now + flushSSSModelRequests(); - // Waiting Instance handling - double deltaT = _DeltaSystemTimeBetweenRender; - clamp (deltaT, 0.01, 0.1); - updateWaitingInstances(deltaT); + // Particle system handling (remove the resources of those which are too far, as their clusters may not have been parsed). + // Note that only a few of them are tested at each call + _ParticleSystemManager.refreshModels(ClipTrav.WorldFrustumPyramid, ClipTrav.CamPos); + + // Waiting Instance handling + double deltaT = _DeltaSystemTimeBetweenRender; + clamp (deltaT, 0.01, 0.1); + updateWaitingInstances(deltaT); + } // Reset profiling _NextRenderProfile= false; @@ -555,7 +558,7 @@ void CScene::endPartRender() // *************************************************************************** -void CScene::renderPart(UScene::TRenderPart rp, bool doHrcPass) +void CScene::renderPart(UScene::TRenderPart rp, bool doHrcPass, bool doTrav, bool keepTrav) { nlassert(_IsRendering); @@ -569,25 +572,31 @@ void CScene::renderPart(UScene::TRenderPart rp, bool doHrcPass) // if first part to be rendered, do the start stuff if (_RenderedPart == UScene::RenderNothing) { - // update water envmap - //updateWaterEnvmap(); RenderTrav.clearWaterModelList(); - _FirstFlare = NULL; - double fNewGlobalSystemTime = NLMISC::CTime::ticksToSecond(NLMISC::CTime::getPerformanceTime()); - if(_GlobalSystemTime==0) - _DeltaSystemTimeBetweenRender= 0.020; - else - _DeltaSystemTimeBetweenRender= fNewGlobalSystemTime - _GlobalSystemTime; - _GlobalSystemTime = fNewGlobalSystemTime; + if (doTrav) + { + // update water envmap + //updateWaterEnvmap(); + _FirstFlare = NULL; + + double fNewGlobalSystemTime = NLMISC::CTime::ticksToSecond(NLMISC::CTime::getPerformanceTime()); + if(_GlobalSystemTime==0) + _DeltaSystemTimeBetweenRender= 0.020; + else + _DeltaSystemTimeBetweenRender= fNewGlobalSystemTime - _GlobalSystemTime; + _GlobalSystemTime = fNewGlobalSystemTime; + } // ++ _NumRender; // nlassert(CurrentCamera); + // update models. updateModels(); + // Use the camera to setup Clip / Render pass. float left, right, bottom, top, znear, zfar; CurrentCamera->getFrustum(left, right, bottom, top, znear, zfar); @@ -609,49 +618,67 @@ void CScene::renderPart(UScene::TRenderPart rp, bool doHrcPass) // **** For all render traversals, traverse them (except the Hrc one), in ascending order. if( doHrcPass ) HrcTrav.traverse(); + else + HrcTrav._MovingObjects.clear(); // Set Cam World Matrix for all trav that need it ClipTrav.setCamMatrix(CurrentCamera->getWorldMatrix()); RenderTrav.setCamMatrix (CurrentCamera->getWorldMatrix()); LoadBalancingTrav.setCamMatrix (CurrentCamera->getWorldMatrix()); - // clip ClipTrav.traverse(); + // animDetail AnimDetailTrav.traverse(); + // loadBalance LoadBalancingTrav.traverse(); - // - if (_RequestParticlesAnimate) + + if (doTrav) { - _ParticleSystemManager.processAnimate(_EllapsedTime); // deals with permanently animated particle systems - _RequestParticlesAnimate = false; + // + if (_RequestParticlesAnimate) + { + _ParticleSystemManager.processAnimate(_EllapsedTime); // deals with permanently animated particle systems + _RequestParticlesAnimate = false; + } } + // Light LightTrav.traverse(); } // render - RenderTrav.traverse(rp, _RenderedPart == UScene::RenderNothing); - // Always must clear shadow caster (if render did not work because of IDriver::isLost()) - RenderTrav.getShadowMapManager().clearAllShadowCasters(); + RenderTrav.traverse(rp, (_RenderedPart == UScene::RenderNothing), doTrav); + if (!keepTrav) + { + // Always must clear shadow caster (if render did not work because of IDriver::isLost()) + RenderTrav.getShadowMapManager().clearAllShadowCasters(); + } // render flare if (rp & UScene::RenderFlare) { - if (_FirstFlare) + if (doTrav) { - IDriver *drv = getDriver(); - CFlareModel::updateOcclusionQueryBegin(drv); - CFlareModel *currFlare = _FirstFlare; - do + if (_FirstFlare) { - currFlare->updateOcclusionQuery(drv); - currFlare = currFlare->Next; + IDriver *drv = getDriver(); + CFlareModel::updateOcclusionQueryBegin(drv); + CFlareModel *currFlare = _FirstFlare; + do + { + currFlare->updateOcclusionQuery(drv); + currFlare = currFlare->Next; + } + while(currFlare); + CFlareModel::updateOcclusionQueryEnd(drv); } - while(currFlare); - CFlareModel::updateOcclusionQueryEnd(drv); + } + else + { + _FirstFlare = NULL; } } _RenderedPart = (UScene::TRenderPart) (_RenderedPart | rp); diff --git a/code/nel/src/3d/scene_user.cpp b/code/nel/src/3d/scene_user.cpp index 908e6a090..0df2439de 100644 --- a/code/nel/src/3d/scene_user.cpp +++ b/code/nel/src/3d/scene_user.cpp @@ -517,7 +517,7 @@ void CSceneUser::beginPartRender() } // *************************************************************************** -void CSceneUser::renderPart(TRenderPart rp) +void CSceneUser::renderPart(TRenderPart rp, bool doHrcPass, bool doTrav, bool keepTrav) { // render the scene. @@ -526,18 +526,18 @@ void CSceneUser::renderPart(TRenderPart rp) if(_Scene.getCam() == NULL) nlerror("render(): try to render with no camera linked (may have been deleted)"); - _Scene.renderPart(rp, true); + _Scene.renderPart(rp, doHrcPass, doTrav, keepTrav); } } // *************************************************************************** -void CSceneUser::endPartRender(bool updateWaitingInstancesFlag, bool restoreMatrixContextAfterRender) +void CSceneUser::endPartRender(bool updateWaitingInstancesFlag, bool restoreMatrixContextAfterRender, bool keepTrav) { // render the scene. { NL3D_HAUTO_RENDER_SCENE_END - _Scene.endPartRender(); + _Scene.endPartRender(keepTrav); } if (updateWaitingInstancesFlag) updateWaitingInstances(); diff --git a/code/nel/src/3d/shaders/compile.bat b/code/nel/src/3d/shaders/compile.bat new file mode 100644 index 000000000..06306a0da --- /dev/null +++ b/code/nel/src/3d/shaders/compile.bat @@ -0,0 +1,3 @@ +cgc -entry fxaa_pp fxaa_pp.cg -profile arbfp1 -O3 -fastmath -fastprecision -o fxaa_pp_arbfp1.txt +cgc -entry fxaa_pp fxaa_pp.cg -profile ps_2_x -O3 -fastmath -fastprecision -o fxaa_pp_ps_2_0.txt +cgc -entry fxaa_vp fxaa_vp.cg -profile arbvp1 -fastmath -fastprecision -o fxaa_vp_arbvp1.txt \ No newline at end of file diff --git a/code/nel/src/3d/shaders/fxaa3_11.h b/code/nel/src/3d/shaders/fxaa3_11.h new file mode 100644 index 000000000..7cdc32c70 --- /dev/null +++ b/code/nel/src/3d/shaders/fxaa3_11.h @@ -0,0 +1,2046 @@ +/*============================================================================ + + +NVIDIA FXAA 3.11 by TIMOTHY LOTTES + + +------------------------------------------------------------------------------ +COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. +------------------------------------------------------------------------------ +TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED +*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA +OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR +LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, +OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE +THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +------------------------------------------------------------------------------ +INTEGRATION CHECKLIST +------------------------------------------------------------------------------ +(1.) +In the shader source, setup defines for the desired configuration. +When providing multiple shaders (for different presets), +simply setup the defines differently in multiple files. +Example, + +#define FXAA_PC 1 +#define FXAA_HLSL_5 1 +#define FXAA_QUALITY__PRESET 12 + +Or, + +#define FXAA_360 1 +Or, + +#define FXAA_PS3 1 +Etc. + +(2.) +Then include this file, + +#include "Fxaa3_11.h" + +(3.) +Then call the FXAA pixel shader from within your desired shader. +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. +As for FXAA 3.11 all inputs for all shaders are the same +to enable easy porting between platforms. + +return FxaaPixelShader(...); + +(4.) +Insure pass prior to FXAA outputs RGBL (see next section). +Or use, + +#define FXAA_GREEN_AS_LUMA 1 + +(5.) +Setup engine to provide the following constants +which are used in the FxaaPixelShader() inputs, + +FxaaFloat2 fxaaQualityRcpFrame, +FxaaFloat4 fxaaConsoleRcpFrameOpt, +FxaaFloat4 fxaaConsoleRcpFrameOpt2, +FxaaFloat4 fxaaConsole360RcpFrameOpt2, +FxaaFloat fxaaQualitySubpix, +FxaaFloat fxaaQualityEdgeThreshold, +FxaaFloat fxaaQualityEdgeThresholdMin, +FxaaFloat fxaaConsoleEdgeSharpness, +FxaaFloat fxaaConsoleEdgeThreshold, +FxaaFloat fxaaConsoleEdgeThresholdMin, +FxaaFloat4 fxaaConsole360ConstDir + +Look at the FXAA Quality FxaaPixelShader() for docs on inputs. + +(6.) +Have FXAA vertex shader run as a full screen triangle, +and output "pos" and "fxaaConsolePosPos" +such that inputs in the pixel shader provide, + +// {xy} = center of pixel +FxaaFloat2 pos, + +// {xy__} = upper left of pixel +// {__zw} = lower right of pixel +FxaaFloat4 fxaaConsolePosPos, + +(7.) +Insure the texture sampler(s) used by FXAA are set to bilinear filtering. + + +------------------------------------------------------------------------------ +INTEGRATION - RGBL AND COLORSPACE +------------------------------------------------------------------------------ +FXAA3 requires RGBL as input unless the following is set, + +#define FXAA_GREEN_AS_LUMA 1 + +In which case the engine uses green in place of luma, +and requires RGB input is in a non-linear colorspace. + +RGB should be LDR (low dynamic range). +Specifically do FXAA after tonemapping. + +RGB data as returned by a texture fetch can be non-linear, +or linear when FXAA_GREEN_AS_LUMA is not set. +Note an "sRGB format" texture counts as linear, +because the result of a texture fetch is linear data. +Regular "RGBA8" textures in the sRGB colorspace are non-linear. + +If FXAA_GREEN_AS_LUMA is not set, +luma must be stored in the alpha channel prior to running FXAA. +This luma should be in a perceptual space (could be gamma 2.0). +Example pass before FXAA where output is gamma 2.0 encoded, + +color.rgb = ToneMap(color.rgb); // linear color output +color.rgb = sqrt(color.rgb); // gamma 2.0 color output +return color; + +To use FXAA, + +color.rgb = ToneMap(color.rgb); // linear color output +color.rgb = sqrt(color.rgb); // gamma 2.0 color output +color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma +return color; + +Another example where output is linear encoded, +say for instance writing to an sRGB formated render target, +where the render target does the conversion back to sRGB after blending, + +color.rgb = ToneMap(color.rgb); // linear color output +return color; + +To use FXAA, + +color.rgb = ToneMap(color.rgb); // linear color output +color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma +return color; + +Getting luma correct is required for the algorithm to work correctly. + + +------------------------------------------------------------------------------ +BEING LINEARLY CORRECT? +------------------------------------------------------------------------------ +Applying FXAA to a framebuffer with linear RGB color will look worse. +This is very counter intuitive, but happends to be true in this case. +The reason is because dithering artifacts will be more visiable +in a linear colorspace. + + +------------------------------------------------------------------------------ +COMPLEX INTEGRATION +------------------------------------------------------------------------------ +Q. What if the engine is blending into RGB before wanting to run FXAA? + +A. In the last opaque pass prior to FXAA, +have the pass write out luma into alpha. +Then blend into RGB only. +FXAA should be able to run ok +assuming the blending pass did not any add aliasing. +This should be the common case for particles and common blending passes. + +A. Or use FXAA_GREEN_AS_LUMA. + +============================================================================*/ + +/*============================================================================ + +INTEGRATION KNOBS + +============================================================================*/ +// +// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). +// FXAA_360_OPT is a prototype for the new optimized 360 version. +// +// 1 = Use API. +// 0 = Don't use API. +// +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PS3 +#define FXAA_PS3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360 +#define FXAA_360 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_360_OPT +#define FXAA_360_OPT 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_PC +// +// FXAA Quality +// The high quality PC algorithm. +// +#define FXAA_PC 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_PC_CONSOLE +// +// The console algorithm for PC is included +// for developers targeting really low spec machines. +// Likely better to just run FXAA_PC, and use a really low preset. +// +#define FXAA_PC_CONSOLE 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_120 +#define FXAA_GLSL_120 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_130 +#define FXAA_GLSL_130 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_3 +#define FXAA_HLSL_3 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_4 +#define FXAA_HLSL_4 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_HLSL_5 +#define FXAA_HLSL_5 0 +#endif +/*==========================================================================*/ +#ifndef FXAA_GREEN_AS_LUMA +// +// For those using non-linear color, +// and either not able to get luma in alpha, or not wanting to, +// this enables FXAA to run using green as a proxy for luma. +// So with this enabled, no need to pack luma in alpha. +// +// This will turn off AA on anything which lacks some amount of green. +// Pure red and blue or combination of only R and B, will get no AA. +// +// Might want to lower the settings for both, +// fxaaConsoleEdgeThresholdMin +// fxaaQualityEdgeThresholdMin +// In order to insure AA does not get turned off on colors +// which contain a minor amount of green. +// +// 1 = On. +// 0 = Off. +// +#define FXAA_GREEN_AS_LUMA 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_EARLY_EXIT +// +// Controls algorithm's early exit path. +// On PS3 turning this ON adds 2 cycles to the shader. +// On 360 turning this OFF adds 10ths of a millisecond to the shader. +// Turning this off on console will result in a more blurry image. +// So this defaults to on. +// +// 1 = On. +// 0 = Off. +// +#define FXAA_EARLY_EXIT 1 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_DISCARD +// +// Only valid for PC OpenGL currently. +// Probably will not work when FXAA_GREEN_AS_LUMA = 1. +// +// 1 = Use discard on pixels which don't need AA. +// For APIs which enable concurrent TEX+ROP from same surface. +// 0 = Return unchanged color on pixels which don't need AA. +// +#define FXAA_DISCARD 0 +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_FAST_PIXEL_OFFSET +// +// Used for GLSL 120 only. +// +// 1 = GL API supports fast pixel offsets +// 0 = do not use fast pixel offsets +// +#ifdef GL_EXT_gpu_shader4 +#define FXAA_FAST_PIXEL_OFFSET 1 +#endif +#ifdef GL_NV_gpu_shader5 +#define FXAA_FAST_PIXEL_OFFSET 1 +#endif +#ifdef GL_ARB_gpu_shader5 +#define FXAA_FAST_PIXEL_OFFSET 1 +#endif +#ifndef FXAA_FAST_PIXEL_OFFSET +#define FXAA_FAST_PIXEL_OFFSET 0 +#endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_GATHER4_ALPHA +// +// 1 = API supports gather4 on alpha channel. +// 0 = API does not support gather4 on alpha channel. +// +#if (FXAA_HLSL_5 == 1) +#define FXAA_GATHER4_ALPHA 1 +#endif +#ifdef GL_ARB_gpu_shader5 +#define FXAA_GATHER4_ALPHA 1 +#endif +#ifdef GL_NV_gpu_shader5 +#define FXAA_GATHER4_ALPHA 1 +#endif +#ifndef FXAA_GATHER4_ALPHA +#define FXAA_GATHER4_ALPHA 0 +#endif +#endif + +/*============================================================================ +FXAA CONSOLE PS3 - TUNING KNOBS +============================================================================*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS +// +// Consoles the sharpness of edges on PS3 only. +// Non-PS3 tuning is done with shader input. +// +// Due to the PS3 being ALU bound, +// there are only two safe values here: 4 and 8. +// These options use the shaders ability to a free *|/ by 2|4|8. +// +// 8.0 is sharper +// 4.0 is softer +// 2.0 is really soft (good for vector graphics inputs) +// +#if 1 +#define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0 +#endif +#if 0 +#define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0 +#endif +#if 0 +#define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0 +#endif +#endif +/*--------------------------------------------------------------------------*/ +#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD +// +// Only effects PS3. +// Non-PS3 tuning is done with shader input. +// +// The minimum amount of local contrast required to apply algorithm. +// The console setting has a different mapping than the quality setting. +// +// This only applies when FXAA_EARLY_EXIT is 1. +// +// Due to the PS3 being ALU bound, +// there are only two safe values here: 0.25 and 0.125. +// These options use the shaders ability to a free *|/ by 2|4|8. +// +// 0.125 leaves less aliasing, but is softer +// 0.25 leaves more aliasing, and is sharper +// +#if 1 +#define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125 +#else +#define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25 +#endif +#endif + +/*============================================================================ +FXAA QUALITY - TUNING KNOBS +------------------------------------------------------------------------------ +NOTE the other tuning knobs are now in the shader function inputs! +============================================================================*/ +#ifndef FXAA_QUALITY__PRESET +// +// Choose the quality preset. +// This needs to be compiled into the shader as it effects code. +// Best option to include multiple presets is to +// in each shader define the preset, then include this file. +// +// OPTIONS +// ----------------------------------------------------------------------- +// 10 to 15 - default medium dither (10=fastest, 15=highest quality) +// 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) +// 39 - no dither, very expensive +// +// NOTES +// ----------------------------------------------------------------------- +// 12 = slightly faster then FXAA 3.9 and higher edge quality (default) +// 13 = about same speed as FXAA 3.9 and better than 12 +// 23 = closest to FXAA 3.9 visually and performance wise +// _ = the lowest digit is directly related to performance +// _ = the highest digit is directly related to style +// +#define FXAA_QUALITY__PRESET 12 +#endif + + +/*============================================================================ + +FXAA QUALITY - PRESETS + +============================================================================*/ + +/*============================================================================ +FXAA QUALITY - MEDIUM DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 10) +#define FXAA_QUALITY__PS 3 +#define FXAA_QUALITY__P0 1.5 +#define FXAA_QUALITY__P1 3.0 +#define FXAA_QUALITY__P2 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 11) +#define FXAA_QUALITY__PS 4 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 3.0 +#define FXAA_QUALITY__P3 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 12) +#define FXAA_QUALITY__PS 5 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 4.0 +#define FXAA_QUALITY__P4 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 13) +#define FXAA_QUALITY__PS 6 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 4.0 +#define FXAA_QUALITY__P5 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 14) +#define FXAA_QUALITY__PS 7 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 4.0 +#define FXAA_QUALITY__P6 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 15) +#define FXAA_QUALITY__PS 8 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 4.0 +#define FXAA_QUALITY__P7 12.0 +#endif + +/*============================================================================ +FXAA QUALITY - LOW DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 20) +#define FXAA_QUALITY__PS 3 +#define FXAA_QUALITY__P0 1.5 +#define FXAA_QUALITY__P1 2.0 +#define FXAA_QUALITY__P2 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 21) +#define FXAA_QUALITY__PS 4 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 22) +#define FXAA_QUALITY__PS 5 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 23) +#define FXAA_QUALITY__PS 6 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 24) +#define FXAA_QUALITY__PS 7 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 3.0 +#define FXAA_QUALITY__P6 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 25) +#define FXAA_QUALITY__PS 8 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 4.0 +#define FXAA_QUALITY__P7 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 26) +#define FXAA_QUALITY__PS 9 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 4.0 +#define FXAA_QUALITY__P8 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 27) +#define FXAA_QUALITY__PS 10 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 2.0 +#define FXAA_QUALITY__P8 4.0 +#define FXAA_QUALITY__P9 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 28) +#define FXAA_QUALITY__PS 11 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 2.0 +#define FXAA_QUALITY__P8 2.0 +#define FXAA_QUALITY__P9 4.0 +#define FXAA_QUALITY__P10 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 29) +#define FXAA_QUALITY__PS 12 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 2.0 +#define FXAA_QUALITY__P8 2.0 +#define FXAA_QUALITY__P9 2.0 +#define FXAA_QUALITY__P10 4.0 +#define FXAA_QUALITY__P11 8.0 +#endif + +/*============================================================================ +FXAA QUALITY - EXTREME QUALITY +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 39) +#define FXAA_QUALITY__PS 12 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.0 +#define FXAA_QUALITY__P2 1.0 +#define FXAA_QUALITY__P3 1.0 +#define FXAA_QUALITY__P4 1.0 +#define FXAA_QUALITY__P5 1.5 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 2.0 +#define FXAA_QUALITY__P8 2.0 +#define FXAA_QUALITY__P9 2.0 +#define FXAA_QUALITY__P10 4.0 +#define FXAA_QUALITY__P11 8.0 +#endif + + + +/*============================================================================ + +API PORTING + +============================================================================*/ +#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) +#define FxaaBool bool +#define FxaaDiscard discard +#define FxaaFloat float +#define FxaaFloat2 vec2 +#define FxaaFloat3 vec3 +#define FxaaFloat4 vec4 +#define FxaaHalf float +#define FxaaHalf2 vec2 +#define FxaaHalf3 vec3 +#define FxaaHalf4 vec4 +#define FxaaInt2 ivec2 +#define FxaaSat(x) clamp(x, 0.0, 1.0) +#define FxaaTex sampler2D +#else +#define FxaaBool bool +#define FxaaDiscard clip(-1) +#define FxaaFloat float +#define FxaaFloat2 float2 +#define FxaaFloat3 float3 +#define FxaaFloat4 float4 +#define FxaaHalf half +#define FxaaHalf2 half2 +#define FxaaHalf3 half3 +#define FxaaHalf4 half4 +#define FxaaSat(x) saturate(x) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_120 == 1) +// Requires, +// #version 120 +// And at least, +// #extension GL_EXT_gpu_shader4 : enable +// (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) +#define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) +#if (FXAA_FAST_PIXEL_OFFSET == 1) +#define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) +#else +#define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) +#endif +#if (FXAA_GATHER4_ALPHA == 1) +// use #extension GL_ARB_gpu_shader5 : enable +#define FxaaTexAlpha4(t, p) textureGather(t, p, 3) +#define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) +#define FxaaTexGreen4(t, p) textureGather(t, p, 1) +#define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) +#endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_130 == 1) +// Requires "#version 130" or better +#define FxaaTexTop(t, p) textureLod(t, p, 0.0) +#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) +#if (FXAA_GATHER4_ALPHA == 1) +// use #extension GL_ARB_gpu_shader5 : enable +#define FxaaTexAlpha4(t, p) textureGather(t, p, 3) +#define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) +#define FxaaTexGreen4(t, p) textureGather(t, p, 1) +#define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) +#endif +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) +#define FxaaInt2 float2 +#define FxaaTex sampler2D +#define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) +#define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_4 == 1) +#define FxaaInt2 int2 +struct FxaaTex { SamplerState smpl; Texture2D tex; }; +#define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) +#define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_HLSL_5 == 1) +#define FxaaInt2 int2 +struct FxaaTex { SamplerState smpl; Texture2D tex; }; +#define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) +#define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) +#define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) +#define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) +#define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p) +#define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o) +#endif + +#undef FxaaTexTop +#define FxaaTexTop(t, p) tex2D(t, p) +#undef FxaaTexOff +#define FxaaTexOff(t, p, o, r) tex2D(t, p + (o * r)) + +/*============================================================================ +GREEN AS LUMA OPTION SUPPORT FUNCTION +============================================================================*/ +#if (FXAA_GREEN_AS_LUMA == 0) +FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } +#else +FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } +#endif + + + + +/*============================================================================ + +FXAA3 QUALITY - PC + +============================================================================*/ +#if (FXAA_PC == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( +// +// Use noperspective interpolation here (turn off perspective interpolation). +// {xy} = center of pixel +FxaaFloat2 pos, +// +// Used only for FXAA Console, and not used on the 360 version. +// Use noperspective interpolation here (turn off perspective interpolation). +// {xy__} = upper left of pixel +// {__zw} = lower right of pixel +//FxaaFloat4 fxaaConsolePosPos, +// +// Input color texture. +// {rgb_} = color in linear or perceptual color space +// if (FXAA_GREEN_AS_LUMA == 0) +// {___a} = luma in perceptual color space (not linear) +FxaaTex tex, +// +// Only used on the optimized 360 version of FXAA Console. +// For everything but 360, just use the same input here as for "tex". +// For 360, same texture, just alias with a 2nd sampler. +// This sampler needs to have an exponent bias of -1. +//FxaaTex fxaaConsole360TexExpBiasNegOne, +// +// Only used on the optimized 360 version of FXAA Console. +// For everything but 360, just use the same input here as for "tex". +// For 360, same texture, just alias with a 3nd sampler. +// This sampler needs to have an exponent bias of -2. +//FxaaTex fxaaConsole360TexExpBiasNegTwo, +// +// Only used on FXAA Quality. +// This must be from a constant/uniform. +// {x_} = 1.0/screenWidthInPixels +// {_y} = 1.0/screenHeightInPixels +FxaaFloat2 fxaaQualityRcpFrame, +// +// Only used on FXAA Console. +// This must be from a constant/uniform. +// This effects sub-pixel AA quality and inversely sharpness. +// Where N ranges between, +// N = 0.50 (default) +// N = 0.33 (sharper) +// {x___} = -N/screenWidthInPixels +// {_y__} = -N/screenHeightInPixels +// {__z_} = N/screenWidthInPixels +// {___w} = N/screenHeightInPixels +//FxaaFloat4 fxaaConsoleRcpFrameOpt, +// +// Only used on FXAA Console. +// Not used on 360, but used on PS3 and PC. +// This must be from a constant/uniform. +// {x___} = -2.0/screenWidthInPixels +// {_y__} = -2.0/screenHeightInPixels +// {__z_} = 2.0/screenWidthInPixels +// {___w} = 2.0/screenHeightInPixels +//FxaaFloat4 fxaaConsoleRcpFrameOpt2, +// +// Only used on FXAA Console. +// Only used on 360 in place of fxaaConsoleRcpFrameOpt2. +// This must be from a constant/uniform. +// {x___} = 8.0/screenWidthInPixels +// {_y__} = 8.0/screenHeightInPixels +// {__z_} = -4.0/screenWidthInPixels +// {___w} = -4.0/screenHeightInPixels +//FxaaFloat4 fxaaConsole360RcpFrameOpt2, +// +// Only used on FXAA Quality. +// This used to be the FXAA_QUALITY__SUBPIX define. +// It is here now to allow easier tuning. +// Choose the amount of sub-pixel aliasing removal. +// This can effect sharpness. +// 1.00 - upper limit (softer) +// 0.75 - default amount of filtering +// 0.50 - lower limit (sharper, less sub-pixel aliasing removal) +// 0.25 - almost off +// 0.00 - completely off +FxaaFloat fxaaQualitySubpix, +// +// Only used on FXAA Quality. +// This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. +// It is here now to allow easier tuning. +// The minimum amount of local contrast required to apply algorithm. +// 0.333 - too little (faster) +// 0.250 - low quality +// 0.166 - default +// 0.125 - high quality +// 0.063 - overkill (slower) +FxaaFloat fxaaQualityEdgeThreshold, +// +// Only used on FXAA Quality. +// This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. +// It is here now to allow easier tuning. +// Trims the algorithm from processing darks. +// 0.0833 - upper limit (default, the start of visible unfiltered edges) +// 0.0625 - high quality (faster) +// 0.0312 - visible limit (slower) +// Special notes when using FXAA_GREEN_AS_LUMA, +// Likely want to set this to zero. +// As colors that are mostly not-green +// will appear very dark in the green channel! +// Tune by looking at mostly non-green content, +// then start at zero and increase until aliasing is a problem. +FxaaFloat fxaaQualityEdgeThresholdMin +// +// Only used on FXAA Console. +// This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. +// It is here now to allow easier tuning. +// This does not effect PS3, as this needs to be compiled in. +// Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. +// Due to the PS3 being ALU bound, +// there are only three safe values here: 2 and 4 and 8. +// These options use the shaders ability to a free *|/ by 2|4|8. +// For all other platforms can be a non-power of two. +// 8.0 is sharper (default!!!) +// 4.0 is softer +// 2.0 is really soft (good only for vector graphics inputs) +//FxaaFloat fxaaConsoleEdgeSharpness, +// +// Only used on FXAA Console. +// This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define. +// It is here now to allow easier tuning. +// This does not effect PS3, as this needs to be compiled in. +// Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3. +// Due to the PS3 being ALU bound, +// there are only two safe values here: 1/4 and 1/8. +// These options use the shaders ability to a free *|/ by 2|4|8. +// The console setting has a different mapping than the quality setting. +// Other platforms can use other values. +// 0.125 leaves less aliasing, but is softer (default!!!) +// 0.25 leaves more aliasing, and is sharper +//FxaaFloat fxaaConsoleEdgeThreshold, +// +// Only used on FXAA Console. +// This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define. +// It is here now to allow easier tuning. +// Trims the algorithm from processing darks. +// The console setting has a different mapping than the quality setting. +// This only applies when FXAA_EARLY_EXIT is 1. +// This does not apply to PS3, +// PS3 was simplified to avoid more shader instructions. +// 0.06 - faster but more aliasing in darks +// 0.05 - default +// 0.04 - slower and less aliasing in darks +// Special notes when using FXAA_GREEN_AS_LUMA, +// Likely want to set this to zero. +// As colors that are mostly not-green +// will appear very dark in the green channel! +// Tune by looking at mostly non-green content, +// then start at zero and increase until aliasing is a problem. +//FxaaFloat fxaaConsoleEdgeThresholdMin, +// +// Extra constants for 360 FXAA Console only. +// Use zeros or anything else for other platforms. +// These must be in physical constant registers and NOT immedates. +// Immedates will result in compiler un-optimizing. +// {xyzw} = float4(1.0, -1.0, 0.25, -0.25) +//FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +FxaaFloat2 posM; +posM.x = pos.x; +posM.y = pos.y; +#if (FXAA_GATHER4_ALPHA == 1) +#if (FXAA_DISCARD == 0) +FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); +#if (FXAA_GREEN_AS_LUMA == 0) +#define lumaM rgbyM.w +#else +#define lumaM rgbyM.y +#endif +#endif +#if (FXAA_GREEN_AS_LUMA == 0) +FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); +FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); +#else +FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); +FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); +#endif +#if (FXAA_DISCARD == 1) +#define lumaM luma4A.w +#endif +#define lumaE luma4A.z +#define lumaS luma4A.x +#define lumaSE luma4A.y +#define lumaNW luma4B.w +#define lumaN luma4B.z +#define lumaW luma4B.x +#else +FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); +#if (FXAA_GREEN_AS_LUMA == 0) +#define lumaM rgbyM.w +#else +#define lumaM rgbyM.y +#endif +FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); +FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); +FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); +FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); +#endif +/*--------------------------------------------------------------------------*/ +FxaaFloat maxSM = max(lumaS, lumaM); +FxaaFloat minSM = min(lumaS, lumaM); +FxaaFloat maxESM = max(lumaE, maxSM); +FxaaFloat minESM = min(lumaE, minSM); +FxaaFloat maxWN = max(lumaN, lumaW); +FxaaFloat minWN = min(lumaN, lumaW); +FxaaFloat rangeMax = max(maxWN, maxESM); +FxaaFloat rangeMin = min(minWN, minESM); +FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; +FxaaFloat range = rangeMax - rangeMin; +FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); +FxaaBool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ +if(earlyExit) +#if (FXAA_DISCARD == 1) +FxaaDiscard; +#else +return rgbyM; +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_GATHER4_ALPHA == 0) +FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); +FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); +FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); +FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); +#else +FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy)); +FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); +#endif +/*--------------------------------------------------------------------------*/ +FxaaFloat lumaNS = lumaN + lumaS; +FxaaFloat lumaWE = lumaW + lumaE; +FxaaFloat subpixRcpRange = 1.0/range; +FxaaFloat subpixNSWE = lumaNS + lumaWE; +FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; +FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; +/*--------------------------------------------------------------------------*/ +FxaaFloat lumaNESE = lumaNE + lumaSE; +FxaaFloat lumaNWNE = lumaNW + lumaNE; +FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; +FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; +/*--------------------------------------------------------------------------*/ +FxaaFloat lumaNWSW = lumaNW + lumaSW; +FxaaFloat lumaSWSE = lumaSW + lumaSE; +FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); +FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); +FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; +FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; +FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; +FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; +/*--------------------------------------------------------------------------*/ +FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; +FxaaFloat lengthSign = fxaaQualityRcpFrame.x; +FxaaBool horzSpan = edgeHorz >= edgeVert; +FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ +if(!horzSpan) lumaN = lumaW; +if(!horzSpan) lumaS = lumaE; +if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; +FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ +FxaaFloat gradientN = lumaN - lumaM; +FxaaFloat gradientS = lumaS - lumaM; +FxaaFloat lumaNN = lumaN + lumaM; +FxaaFloat lumaSS = lumaS + lumaM; +FxaaBool pairN = abs(gradientN) >= abs(gradientS); +FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); +if(pairN) lengthSign = -lengthSign; +FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ +FxaaFloat2 posB; +posB.x = posM.x; +posB.y = posM.y; +FxaaFloat2 offNP; +offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; +offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; +if(!horzSpan) posB.x += lengthSign * 0.5; +if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ +FxaaFloat2 posN; +posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; +posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; +FxaaFloat2 posP; +posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; +posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; +FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; +FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); +FxaaFloat subpixE = subpixC * subpixC; +FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); +/*--------------------------------------------------------------------------*/ +if(!pairN) lumaNN = lumaSS; +FxaaFloat gradientScaled = gradient * 1.0/4.0; +FxaaFloat lumaMM = lumaM - lumaNN * 0.5; +FxaaFloat subpixF = subpixD * subpixE; +FxaaBool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ +lumaEndN -= lumaNN * 0.5; +lumaEndP -= lumaNN * 0.5; +FxaaBool doneN = abs(lumaEndN) >= gradientScaled; +FxaaBool doneP = abs(lumaEndP) >= gradientScaled; +if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; +if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; +FxaaBool doneNP = (!doneN) || (!doneP); +if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; +if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; +/*--------------------------------------------------------------------------*/ +if(doneNP) { +if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); +if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); +if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; +if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; +doneN = abs(lumaEndN) >= gradientScaled; +doneP = abs(lumaEndP) >= gradientScaled; +if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; +if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; +doneNP = (!doneN) || (!doneP); +if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; +if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 3) +if(doneNP) { +if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); +if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); +if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; +if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; +doneN = abs(lumaEndN) >= gradientScaled; +doneP = abs(lumaEndP) >= gradientScaled; +if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; +if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; +doneNP = (!doneN) || (!doneP); +if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; +if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 4) +if(doneNP) { +if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); +if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); +if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; +if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; +doneN = abs(lumaEndN) >= gradientScaled; +doneP = abs(lumaEndP) >= gradientScaled; +if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; +if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; +doneNP = (!doneN) || (!doneP); +if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; +if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 5) +if(doneNP) { +if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); +if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); +if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; +if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; +doneN = abs(lumaEndN) >= gradientScaled; +doneP = abs(lumaEndP) >= gradientScaled; +if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; +if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; +doneNP = (!doneN) || (!doneP); +if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; +if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 6) +if(doneNP) { +if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); +if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); +if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; +if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; +doneN = abs(lumaEndN) >= gradientScaled; +doneP = abs(lumaEndP) >= gradientScaled; +if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; +if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; +doneNP = (!doneN) || (!doneP); +if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; +if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 7) +if(doneNP) { +if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); +if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); +if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; +if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; +doneN = abs(lumaEndN) >= gradientScaled; +doneP = abs(lumaEndP) >= gradientScaled; +if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; +if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; +doneNP = (!doneN) || (!doneP); +if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; +if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 8) +if(doneNP) { +if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); +if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); +if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; +if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; +doneN = abs(lumaEndN) >= gradientScaled; +doneP = abs(lumaEndP) >= gradientScaled; +if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; +if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; +doneNP = (!doneN) || (!doneP); +if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; +if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 9) +if(doneNP) { +if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); +if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); +if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; +if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; +doneN = abs(lumaEndN) >= gradientScaled; +doneP = abs(lumaEndP) >= gradientScaled; +if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; +if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; +doneNP = (!doneN) || (!doneP); +if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; +if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 10) +if(doneNP) { +if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); +if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); +if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; +if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; +doneN = abs(lumaEndN) >= gradientScaled; +doneP = abs(lumaEndP) >= gradientScaled; +if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; +if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; +doneNP = (!doneN) || (!doneP); +if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; +if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 11) +if(doneNP) { +if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); +if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); +if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; +if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; +doneN = abs(lumaEndN) >= gradientScaled; +doneP = abs(lumaEndP) >= gradientScaled; +if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; +if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; +doneNP = (!doneN) || (!doneP); +if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; +if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 12) +if(doneNP) { +if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); +if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); +if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; +if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; +doneN = abs(lumaEndN) >= gradientScaled; +doneP = abs(lumaEndP) >= gradientScaled; +if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; +if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; +doneNP = (!doneN) || (!doneP); +if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; +if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; +/*--------------------------------------------------------------------------*/ +} +#endif +/*--------------------------------------------------------------------------*/ +} +#endif +/*--------------------------------------------------------------------------*/ +} +#endif +/*--------------------------------------------------------------------------*/ +} +#endif +/*--------------------------------------------------------------------------*/ +} +#endif +/*--------------------------------------------------------------------------*/ +} +#endif +/*--------------------------------------------------------------------------*/ +} +#endif +/*--------------------------------------------------------------------------*/ +} +#endif +/*--------------------------------------------------------------------------*/ +} +#endif +/*--------------------------------------------------------------------------*/ +} +#endif +/*--------------------------------------------------------------------------*/ +} +/*--------------------------------------------------------------------------*/ +FxaaFloat dstN = posM.x - posN.x; +FxaaFloat dstP = posP.x - posM.x; +if(!horzSpan) dstN = posM.y - posN.y; +if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ +FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; +FxaaFloat spanLength = (dstP + dstN); +FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; +FxaaFloat spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ +FxaaBool directionN = dstN < dstP; +FxaaFloat dst = min(dstN, dstP); +FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; +FxaaFloat subpixG = subpixF * subpixF; +FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; +FxaaFloat subpixH = subpixG * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ +FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; +FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); +if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; +if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; +#if (FXAA_DISCARD == 1) +return FxaaTexTop(tex, posM); +#else +return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); +#endif +} +/*==========================================================================*/ +#endif + + + + +/*============================================================================ + +FXAA3 CONSOLE - PC VERSION +------------------------------------------------------------------------------ +Instead of using this on PC, I'd suggest just using FXAA Quality with +#define FXAA_QUALITY__PRESET 10 +Or +#define FXAA_QUALITY__PRESET 20 +Either are higher qualilty and almost as fast as this on modern PC GPUs. +============================================================================*/ +#if (FXAA_PC_CONSOLE == 1) +/*--------------------------------------------------------------------------*/ +FxaaFloat4 FxaaPixelShader( +// See FXAA Quality FxaaPixelShader() source for docs on Inputs! +FxaaFloat2 pos, +FxaaFloat4 fxaaConsolePosPos, +FxaaTex tex, +FxaaTex fxaaConsole360TexExpBiasNegOne, +FxaaTex fxaaConsole360TexExpBiasNegTwo, +FxaaFloat2 fxaaQualityRcpFrame, +FxaaFloat4 fxaaConsoleRcpFrameOpt, +FxaaFloat4 fxaaConsoleRcpFrameOpt2, +FxaaFloat4 fxaaConsole360RcpFrameOpt2, +FxaaFloat fxaaQualitySubpix, +FxaaFloat fxaaQualityEdgeThreshold, +FxaaFloat fxaaQualityEdgeThresholdMin, +FxaaFloat fxaaConsoleEdgeSharpness, +FxaaFloat fxaaConsoleEdgeThreshold, +FxaaFloat fxaaConsoleEdgeThresholdMin, +FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy)); +FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw)); +FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy)); +FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw)); +/*--------------------------------------------------------------------------*/ +FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy); +#if (FXAA_GREEN_AS_LUMA == 0) +FxaaFloat lumaM = rgbyM.w; +#else +FxaaFloat lumaM = rgbyM.y; +#endif +/*--------------------------------------------------------------------------*/ +FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw); +lumaNe += 1.0/384.0; +FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw); +/*--------------------------------------------------------------------------*/ +FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe); +FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe); +/*--------------------------------------------------------------------------*/ +FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw); +FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw); +/*--------------------------------------------------------------------------*/ +FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold; +/*--------------------------------------------------------------------------*/ +FxaaFloat lumaMinM = min(lumaMin, lumaM); +FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled); +FxaaFloat lumaMaxM = max(lumaMax, lumaM); +FxaaFloat dirSwMinusNe = lumaSw - lumaNe; +FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM; +FxaaFloat dirSeMinusNw = lumaSe - lumaNw; +if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM; +/*--------------------------------------------------------------------------*/ +FxaaFloat2 dir; +dir.x = dirSwMinusNe + dirSeMinusNw; +dir.y = dirSwMinusNe - dirSeMinusNw; +/*--------------------------------------------------------------------------*/ +FxaaFloat2 dir1 = normalize(dir.xy); +FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw); +FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw); +/*--------------------------------------------------------------------------*/ +FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness; +FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); +/*--------------------------------------------------------------------------*/ +FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw); +FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw); +/*--------------------------------------------------------------------------*/ +FxaaFloat4 rgbyA = rgbyN1 + rgbyP1; +FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25); +/*--------------------------------------------------------------------------*/ +#if (FXAA_GREEN_AS_LUMA == 0) +FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); +#else +FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax); +#endif +if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5; +return rgbyB; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + +FXAA3 CONSOLE - 360 PIXEL SHADER + +------------------------------------------------------------------------------ +This optimized version thanks to suggestions from Andy Luedke. +Should be fully tex bound in all cases. +As of the FXAA 3.11 release, I have still not tested this code, +however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10. +And note this is replacing the old unoptimized version. +If it does not work, please let me know so I can fix it. +============================================================================*/ +#if (FXAA_360 == 1) +/*--------------------------------------------------------------------------*/ +[reduceTempRegUsage(4)] +float4 FxaaPixelShader( +// See FXAA Quality FxaaPixelShader() source for docs on Inputs! +FxaaFloat2 pos, +FxaaFloat4 fxaaConsolePosPos, +FxaaTex tex, +FxaaTex fxaaConsole360TexExpBiasNegOne, +FxaaTex fxaaConsole360TexExpBiasNegTwo, +FxaaFloat2 fxaaQualityRcpFrame, +FxaaFloat4 fxaaConsoleRcpFrameOpt, +FxaaFloat4 fxaaConsoleRcpFrameOpt2, +FxaaFloat4 fxaaConsole360RcpFrameOpt2, +FxaaFloat fxaaQualitySubpix, +FxaaFloat fxaaQualityEdgeThreshold, +FxaaFloat fxaaQualityEdgeThresholdMin, +FxaaFloat fxaaConsoleEdgeSharpness, +FxaaFloat fxaaConsoleEdgeThreshold, +FxaaFloat fxaaConsoleEdgeThresholdMin, +FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +float4 lumaNwNeSwSe; +#if (FXAA_GREEN_AS_LUMA == 0) +asm { +tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false +tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false +tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false +tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false +}; +#else +asm { +tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false +tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false +tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false +tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false +}; +#endif +/*--------------------------------------------------------------------------*/ +lumaNwNeSwSe.y += 1.0/384.0; +float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); +float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); +float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); +float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); +/*--------------------------------------------------------------------------*/ +float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0)); +#if (FXAA_GREEN_AS_LUMA == 0) +float lumaMinM = min(lumaMin, rgbyM.w); +float lumaMaxM = max(lumaMax, rgbyM.w); +#else +float lumaMinM = min(lumaMin, rgbyM.y); +float lumaMaxM = max(lumaMax, rgbyM.y); +#endif +if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM; +/*--------------------------------------------------------------------------*/ +float2 dir; +dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx); +dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy); +dir = normalize(dir); +/*--------------------------------------------------------------------------*/ +float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw; +/*--------------------------------------------------------------------------*/ +float4 dir2; +float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness; +dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5); +dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw; +/*--------------------------------------------------------------------------*/ +float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0)); +float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0)); +float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0)); +float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ +float4 rgbyA = rgbyN1 + rgbyP1; +float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5; +/*--------------------------------------------------------------------------*/ +float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; +rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; +return rgbyR; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + +FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) + +============================================================================== +The code below does not exactly match the assembly. +I have a feeling that 12 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + +--fenable-bx2 --fastmath --fastprecision --nofloatbindings + +------------------------------------------------------------------------------ +NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: +0: texpkb h0.w(TRUE), v5.zyxx, #0 +2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x +4: texpkb h0.w(TRUE), v5.xwxx, #0 +6: addh h0.z(TRUE), -h2, h0.w +7: texpkb h1.w(TRUE), v5, #0 +9: addh h0.x(TRUE), h0.z, -h1.w +10: addh h3.w(TRUE), h0.z, h1 +11: texpkb h2.w(TRUE), v5.zwzz, #0 +13: addh h0.z(TRUE), h3.w, -h2.w +14: addh h0.x(TRUE), h2.w, h0 +15: nrmh h1.xz(TRUE), h0_n +16: minh_m8 h0.x(TRUE), |h1|, |h1.z| +17: maxh h4.w(TRUE), h0, h1 +18: divx h2.xy(TRUE), h1_n.xzzw, h0_n +19: movr r1.zw(TRUE), v4.xxxy +20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww +22: minh h5.w(TRUE), h0, h1 +23: texpkb h0(TRUE), r2.xzxx, #0 +25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 +27: maxh h4.x(TRUE), h2.z, h2.w +28: texpkb h1(TRUE), r0.zwzz, #0 +30: addh_d2 h1(TRUE), h0, h1 +31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz +33: texpkb h0(TRUE), r0, #0 +35: minh h4.z(TRUE), h2, h2.w +36: fenct TRUE +37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz +39: texpkb h2(TRUE), r1, #0 +41: addh_d2 h0(TRUE), h0, h2 +42: maxh h2.w(TRUE), h4, h4.x +43: minh h2.x(TRUE), h5.w, h4.z +44: addh_d2 h0(TRUE), h0, h1 +45: slth h2.x(TRUE), h0.w, h2 +46: sgth h2.w(TRUE), h0, h2 +47: movh h0(TRUE), h0 +48: addx.c0 rc(TRUE), h2, h2.w +49: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- +1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; +| TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; +| SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; +| | | +2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; +| TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; +| SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; +| | | +3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; +| TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; +| SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; +| SCB1 | add | 10: ADDh h3.w, h0.---z, h1; +| | | +4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; +| TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; +| SCB0 | add | 14: ADDh h0.x, h2.w---, h0; +| SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; +| | | +5 | SCT1 | mov | 15: NRMh h1.xz, h0; +| SRB | nrm | 15: NRMh h1.xz, h0; +| SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; +| SCB1 | max | 17: MAXh h4.w, h0, h1; +| | | +6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; +| SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; +| SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; +| SCB1 | min | 22: MINh h5.w, h0, h1; +| | | +7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; +| TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; +| SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; +| SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; +| | | +8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; +| TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; +| SCB0/1 | add | 30: ADDh/2 h1, h0, h1; +| | | +9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; +| SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; +| TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; +| SCB1 | min | 35: MINh h4.z, h2, h2.--w-; +| | | +10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; +| SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; +| TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; +| SCB0/1 | add | 41: ADDh/2 h0, h0, h2; +| | | +11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; +| SCT1 | max | 42: MAXh h2.w, h4, h4.---x; +| SCB0/1 | add | 44: ADDh/2 h0, h0, h1; +| | | +12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; +| SCT1 | set | 46: SGTh h2.w, h0, h2; +| SCB0/1 | mul | 47: MOVh h0, h0; +| | | +13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; +| SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; +Pass SCT TEX SCB +1: 0% 100% 25% +2: 0% 100% 25% +3: 0% 100% 50% +4: 0% 100% 50% +5: 0% 0% 50% +6: 100% 0% 75% +7: 0% 100% 75% +8: 0% 100% 100% +9: 0% 100% 25% +10: 0% 100% 100% +11: 50% 0% 100% +12: 50% 0% 100% +13: 25% 0% 100% + +MEAN: 17% 61% 67% + +Pass SCT0 SCT1 TEX SCB0 SCB1 +1: 0% 0% 100% 0% 100% +2: 0% 0% 100% 0% 100% +3: 0% 0% 100% 100% 100% +4: 0% 0% 100% 100% 100% +5: 0% 0% 0% 100% 100% +6: 100% 100% 0% 100% 100% +7: 0% 0% 100% 100% 100% +8: 0% 0% 100% 100% 100% +9: 0% 0% 100% 0% 100% +10: 0% 0% 100% 100% 100% +11: 100% 100% 0% 100% 100% +12: 100% 100% 0% 100% 100% +13: 100% 0% 0% 100% 100% + +MEAN: 30% 23% 61% 76% 100% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 13 cycles, 3 r regs, 923,076,923 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +//#pragma option O3 +//#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( +// See FXAA Quality FxaaPixelShader() source for docs on Inputs! +FxaaFloat2 pos, +FxaaFloat4 fxaaConsolePosPos, +FxaaTex tex, +//FxaaTex fxaaConsole360TexExpBiasNegOne, +//FxaaTex fxaaConsole360TexExpBiasNegTwo, +//FxaaFloat2 fxaaQualityRcpFrame, +FxaaFloat4 fxaaConsoleRcpFrameOpt, +FxaaFloat4 fxaaConsoleRcpFrameOpt2 +//FxaaFloat4 fxaaConsole360RcpFrameOpt2, +//FxaaFloat fxaaQualitySubpix, +//FxaaFloat fxaaQualityEdgeThreshold, +//FxaaFloat fxaaQualityEdgeThresholdMin, +//FxaaFloat fxaaConsoleEdgeSharpness, +//FxaaFloat fxaaConsoleEdgeThreshold, +//FxaaFloat fxaaConsoleEdgeThresholdMin, +//FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) +half4 dir; +half4 lumaNe = tex2D(tex, fxaaConsolePosPos.zy); // h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); +#if (FXAA_GREEN_AS_LUMA == 0) +lumaNe.w += half(1.0/512.0); +dir.x = -lumaNe.w; +dir.z = -lumaNe.w; +#else +lumaNe.y += half(1.0/512.0); +dir.x = -lumaNe.y; +dir.z = -lumaNe.y; +#endif +/*--------------------------------------------------------------------------*/ +// (2) +half4 lumaSw = tex2D(tex, fxaaConsolePosPos.xw); // h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); +#if (FXAA_GREEN_AS_LUMA == 0) +dir.x += lumaSw.w; +dir.z += lumaSw.w; +#else +dir.x += lumaSw.y; +dir.z += lumaSw.y; +#endif +/*--------------------------------------------------------------------------*/ +// (3) +half4 lumaNw = tex2D(tex, fxaaConsolePosPos.xy); // h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); +#if (FXAA_GREEN_AS_LUMA == 0) +dir.x -= lumaNw.w; +dir.z += lumaNw.w; +#else +dir.x -= lumaNw.y; +dir.z += lumaNw.y; +#endif +/*--------------------------------------------------------------------------*/ +// (4) +half4 lumaSe = tex2D(tex, fxaaConsolePosPos.zw); // h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); +#if (FXAA_GREEN_AS_LUMA == 0) +dir.x += lumaSe.w; +dir.z -= lumaSe.w; +#else +dir.x += lumaSe.y; +dir.z -= lumaSe.y; +#endif +/*--------------------------------------------------------------------------*/ +// (5) +half4 dir1_pos; +dir1_pos.xy = normalize(dir.xz); +half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (6) +half4 dir2_pos; +dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); +dir1_pos.zw = pos.xy; +dir2_pos.zw = pos.xy; +half4 temp1N; +temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (7) +temp1N = tex2D(tex, temp1N.xy); // h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); +half4 rgby1; +rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +/*--------------------------------------------------------------------------*/ +// (8) +rgby1 = tex2D(tex, rgby1.xy); // h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); +rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (9) +half4 temp2N; +temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; +temp2N = tex2D(tex, temp2N.xy); // h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); +/*--------------------------------------------------------------------------*/ +// (10) +half4 rgby2; +rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; +rgby2 = tex2D(tex, rgby2.xy); // h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); +rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (11) +// compilier moves these scalar ops up to other cycles +#if (FXAA_GREEN_AS_LUMA == 0) +half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); +half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); +#else +half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y)); +half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y)); +#endif +rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (12) +#if (FXAA_GREEN_AS_LUMA == 0) +bool twoTapLt = rgby2.w < lumaMin; +bool twoTapGt = rgby2.w > lumaMax; +#else +bool twoTapLt = rgby2.y < lumaMin; +bool twoTapGt = rgby2.y > lumaMax; +#endif +/*--------------------------------------------------------------------------*/ +// (13) +if(twoTapLt || twoTapGt) rgby2 = rgby1; +/*--------------------------------------------------------------------------*/ +return rgby2; } +/*==========================================================================*/ +#endif + + + +/*============================================================================ + +FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) + +============================================================================== +The code mostly matches the assembly. +I have a feeling that 14 cycles is possible, but was not able to get there. +Might have to increase register count to get full performance. +Note this shader does not use perspective interpolation. + +Use the following cgc options, + +--fenable-bx2 --fastmath --fastprecision --nofloatbindings + +Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks). +Will look at fixing this for FXAA 3.12. +------------------------------------------------------------------------------ +NVSHADERPERF OUTPUT +------------------------------------------------------------------------------ +For reference and to aid in debug, output of NVShaderPerf should match this, + +Shader to schedule: +0: texpkb h0.w(TRUE), v5.zyxx, #0 +2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x +4: texpkb h1.w(TRUE), v5.xwxx, #0 +6: addh h0.x(TRUE), h1.w, -h2.y +7: texpkb h2.w(TRUE), v5.zwzz, #0 +9: minh h4.w(TRUE), h2.y, h2 +10: maxh h5.x(TRUE), h2.y, h2.w +11: texpkb h0.w(TRUE), v5, #0 +13: addh h3.w(TRUE), -h0, h0.x +14: addh h0.x(TRUE), h0.w, h0 +15: addh h0.z(TRUE), -h2.w, h0.x +16: addh h0.x(TRUE), h2.w, h3.w +17: minh h5.y(TRUE), h0.w, h1.w +18: nrmh h2.xz(TRUE), h0_n +19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| +20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w +21: movr r1.zw(TRUE), v4.xxxy +22: maxh h2.w(TRUE), h0, h1 +23: fenct TRUE +24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz +26: texpkb h0(TRUE), r0, #0 +28: maxh h5.x(TRUE), h2.w, h5 +29: minh h5.w(TRUE), h5.y, h4 +30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz +32: texpkb h2(TRUE), r1, #0 +34: addh_d2 h2(TRUE), h0, h2 +35: texpkb h1(TRUE), v4, #0 +37: maxh h5.y(TRUE), h5.x, h1.w +38: minh h4.w(TRUE), h1, h5 +39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz +41: texpkb h0(TRUE), r0, #0 +43: addh_m8 h5.z(TRUE), h5.y, -h4.w +44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz +46: texpkb h3(TRUE), r2, #0 +48: addh_d2 h0(TRUE), h0, h3 +49: addh_d2 h3(TRUE), h0, h2 +50: movh h0(TRUE), h3 +51: slth h3.x(TRUE), h3.w, h5.w +52: sgth h3.w(TRUE), h3, h5.x +53: addx.c0 rc(TRUE), h3.x, h3 +54: slth.c0 rc(TRUE), h5.z, h5 +55: movh h0(c0.NE.w), h2 +56: movh h0(c0.NE.x), h1 + +IPU0 ------ Simplified schedule: -------- +Pass | Unit | uOp | PC: Op +-----+--------+------+------------------------- +1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; +| TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; +| SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; +| | | +2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; +| TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; +| SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; +| | | +3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; +| TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; +| SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; +| SCB1 | min | 9: MINh h4.w, h2.---y, h2; +| | | +4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; +| TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; +| SCB0 | add | 14: ADDh h0.x, h0.w---, h0; +| SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; +| | | +5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; +| SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; +| SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; +| | | +6 | SCT1 | mov | 18: NRMh h2.xz, h0; +| SRB | nrm | 18: NRMh h2.xz, h0; +| SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; +| | | +7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; +| SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; +| SCB1 | max | 22: MAXh h2.w, h0, h1; +| | | +8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; +| SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; +| TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; +| SCB0 | max | 28: MAXh h5.x, h2.w---, h5; +| SCB1 | min | 29: MINh h5.w, h5.---y, h4; +| | | +9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; +| SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; +| TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; +| SCB0/1 | add | 34: ADDh/2 h2, h0, h2; +| | | +10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; +| TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; +| SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; +| SCB1 | min | 38: MINh h4.w, h1, h5; +| | | +11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; +| SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; +| TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; +| SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; +| SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; +| | | +12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; +| TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; +| SCB0/1 | add | 48: ADDh/2 h0, h0, h3; +| | | +13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; +| SCB0/1 | mul | 50: MOVh h0, h3; +| | | +14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; +| SCT1 | set | 52: SGTh h3.w, h3, h5.---x; +| SCB0 | set | 54: SLThc0 rc, h5.z---, h5; +| SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; +| | | +15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; +| SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; +Pass SCT TEX SCB +1: 0% 100% 25% +2: 0% 100% 25% +3: 0% 100% 50% +4: 0% 100% 50% +5: 50% 0% 25% +6: 0% 0% 25% +7: 100% 0% 25% +8: 0% 100% 50% +9: 0% 100% 100% +10: 0% 100% 50% +11: 0% 100% 75% +12: 0% 100% 100% +13: 100% 0% 100% +14: 50% 0% 50% +15: 100% 0% 100% + +MEAN: 26% 60% 56% + +Pass SCT0 SCT1 TEX SCB0 SCB1 +1: 0% 0% 100% 100% 0% +2: 0% 0% 100% 100% 0% +3: 0% 0% 100% 100% 100% +4: 0% 0% 100% 100% 100% +5: 100% 100% 0% 100% 0% +6: 0% 0% 0% 0% 100% +7: 100% 100% 0% 0% 100% +8: 0% 0% 100% 100% 100% +9: 0% 0% 100% 100% 100% +10: 0% 0% 100% 100% 100% +11: 0% 0% 100% 100% 100% +12: 0% 0% 100% 100% 100% +13: 100% 100% 0% 100% 100% +14: 100% 100% 0% 100% 100% +15: 100% 100% 0% 100% 100% + +MEAN: 33% 33% 60% 86% 80% +Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 +Results 15 cycles, 3 r regs, 800,000,000 pixels/s +============================================================================*/ +#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) +/*--------------------------------------------------------------------------*/ +#pragma regcount 7 +#pragma disablepc all +//#pragma option O2 +//#pragma option OutColorPrec=fp16 +#pragma texformat default RGBA8 +/*==========================================================================*/ +half4 FxaaPixelShader( +// See FXAA Quality FxaaPixelShader() source for docs on Inputs! +FxaaFloat2 pos, +FxaaFloat4 fxaaConsolePosPos, +FxaaTex tex, +//FxaaTex fxaaConsole360TexExpBiasNegOne, +//FxaaTex fxaaConsole360TexExpBiasNegTwo, +//FxaaFloat2 fxaaQualityRcpFrame, +FxaaFloat4 fxaaConsoleRcpFrameOpt, +FxaaFloat4 fxaaConsoleRcpFrameOpt2 +//FxaaFloat4 fxaaConsole360RcpFrameOpt, +//FxaaFloat fxaaQualitySubpix, +//FxaaFloat fxaaQualityEdgeThreshold, +//FxaaFloat fxaaQualityEdgeThresholdMin, +//FxaaFloat fxaaConsoleEdgeSharpness, +//FxaaFloat fxaaConsoleEdgeThreshold, +//FxaaFloat fxaaConsoleEdgeThresholdMin, +//FxaaFloat4 fxaaConsole360ConstDir +) { +/*--------------------------------------------------------------------------*/ +// (1) +half4 rgbyNe = tex2D(tex, fxaaConsolePosPos.zy); // h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); +#if (FXAA_GREEN_AS_LUMA == 0) +half lumaNe = rgbyNe.w + half(1.0/512.0); +#else +half lumaNe = rgbyNe.y + half(1.0/512.0); +#endif +/*--------------------------------------------------------------------------*/ +// (2) +half4 lumaSw = tex2D(tex, fxaaConsolePosPos.xw); // h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); +#if (FXAA_GREEN_AS_LUMA == 0) +half lumaSwNegNe = lumaSw.w - lumaNe; +#else +half lumaSwNegNe = lumaSw.y - lumaNe; +#endif +/*--------------------------------------------------------------------------*/ +// (3) +half4 lumaNw = tex2D(tex, fxaaConsolePosPos.xy); // h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); +#if (FXAA_GREEN_AS_LUMA == 0) +half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); +half lumaMinNwSw = min(lumaNw.w, lumaSw.w); +#else +half lumaMaxNwSw = max(lumaNw.y, lumaSw.y); +half lumaMinNwSw = min(lumaNw.y, lumaSw.y); +#endif +/*--------------------------------------------------------------------------*/ +// (4) +half4 lumaSe = tex2D(tex, fxaaConsolePosPos.zw); // h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); +#if (FXAA_GREEN_AS_LUMA == 0) +half dirZ = lumaNw.w + lumaSwNegNe; +half dirX = -lumaNw.w + lumaSwNegNe; +#else +half dirZ = lumaNw.y + lumaSwNegNe; +half dirX = -lumaNw.y + lumaSwNegNe; +#endif +/*--------------------------------------------------------------------------*/ +// (5) +half3 dir; +dir.y = 0.0; +#if (FXAA_GREEN_AS_LUMA == 0) +dir.x = lumaSe.w + dirX; +dir.z = -lumaSe.w + dirZ; +half lumaMinNeSe = min(lumaNe, lumaSe.w); +#else +dir.x = lumaSe.y + dirX; +dir.z = -lumaSe.y + dirZ; +half lumaMinNeSe = min(lumaNe, lumaSe.y); +#endif +/*--------------------------------------------------------------------------*/ +// (6) +half4 dir1_pos; +dir1_pos.xy = normalize(dir).xz; +half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); +/*--------------------------------------------------------------------------*/ +// (7) +half4 dir2_pos; +dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); +dir1_pos.zw = pos.xy; +dir2_pos.zw = pos.xy; +#if (FXAA_GREEN_AS_LUMA == 0) +half lumaMaxNeSe = max(lumaNe, lumaSe.w); +#else +half lumaMaxNeSe = max(lumaNe, lumaSe.y); +#endif +/*--------------------------------------------------------------------------*/ +// (8) +half4 temp1N; +temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +temp1N = tex2D(tex, temp1N.xy); // h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); +half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); +half lumaMin = min(lumaMinNwSw, lumaMinNeSe); +/*--------------------------------------------------------------------------*/ +// (9) +half4 rgby1; +rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; +rgby1 = tex2D(tex, rgby1.xy); // h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); +rgby1 = (temp1N + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (10) +half4 rgbyM = tex2D(tex, pos.xy); // h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); +#if (FXAA_GREEN_AS_LUMA == 0) +half lumaMaxM = max(lumaMax, rgbyM.w); +half lumaMinM = min(lumaMin, rgbyM.w); +#else +half lumaMaxM = max(lumaMax, rgbyM.y); +half lumaMinM = min(lumaMin, rgbyM.y); +#endif +/*--------------------------------------------------------------------------*/ +// (11) +half4 temp2N; +temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; +temp2N = tex2D(tex, temp2N.xy); // h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); +half4 rgby2; +rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; +half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD; +/*--------------------------------------------------------------------------*/ +// (12) +rgby2 = tex2D(tex, rgby2.xy); // h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); +rgby2 = (temp2N + rgby2) * 0.5; +/*--------------------------------------------------------------------------*/ +// (13) +rgby2 = (rgby2 + rgby1) * 0.5; +/*--------------------------------------------------------------------------*/ +// (14) +#if (FXAA_GREEN_AS_LUMA == 0) +bool twoTapLt = rgby2.w < lumaMin; +bool twoTapGt = rgby2.w > lumaMax; +#else +bool twoTapLt = rgby2.y < lumaMin; +bool twoTapGt = rgby2.y > lumaMax; +#endif +bool earlyExit = lumaRangeM < lumaMax; +bool twoTap = twoTapLt || twoTapGt; +/*--------------------------------------------------------------------------*/ +// (15) +if(twoTap) rgby2 = rgby1; +if(earlyExit) rgby2 = rgbyM; +/*--------------------------------------------------------------------------*/ +return rgby2; } +/*==========================================================================*/ +#endif \ No newline at end of file diff --git a/code/nel/src/3d/shaders/fxaa_pp.cg b/code/nel/src/3d/shaders/fxaa_pp.cg new file mode 100644 index 000000000..49622f206 --- /dev/null +++ b/code/nel/src/3d/shaders/fxaa_pp.cg @@ -0,0 +1,91 @@ + +#define FXAA_PC 1 +#define FXAA_HLSL_3 1 +#define FXAA_QUALITY__PRESET 12 +#define FXAA_EARLY_EXIT 0 +#define FXAA_GREEN_AS_LUMA 1 + +#define h4tex2Dlod tex2Dlod +#define half4 float4 +#define half3 float3 +#define half2 float2 +#define half float + +#include "fxaa3_11.h" + +void fxaa_pp( + // Per fragment parameters + float2 pos : TEXCOORD0, +#if (FXAA_PS3 == 1) + float4 fxaaConsolePosPos : TEXCOORD1, +#endif + + // Fragment program constants +#if (FXAA_PC == 1) + uniform float2 fxaaQualityRcpFrame, + uniform float fxaaQualitySubpix, + uniform float fxaaQualityEdgeThreshold, + uniform float fxaaQualityEdgeThresholdMin, +#else + uniform float4 fxaaConsoleRcpFrameOpt, + uniform float4 fxaaConsoleRcpFrameOpt2, +#endif + uniform sampler2D nlTex0 : TEX0, + + // Output color + out float4 oCol : COLOR +) +{ +#if (FXAA_PC == 1) + oCol = FxaaPixelShader( + pos, + nlTex0, + fxaaQualityRcpFrame, + fxaaQualitySubpix, + fxaaQualityEdgeThreshold, + fxaaQualityEdgeThresholdMin + ); +#else + oCol = FxaaPixelShader( + pos, + fxaaConsolePosPos, + nlTex0, + fxaaConsoleRcpFrameOpt, + fxaaConsoleRcpFrameOpt2 + ); +#endif +} + +/* +Have FXAA vertex shader run as a full screen triangle, +and output "pos" and "fxaaConsolePosPos" +such that inputs in the pixel shader provide, + +// {xy} = center of pixel +FxaaFloat2 pos, + +// {xy__} = upper left of pixel +// {__zw} = lower right of pixel +FxaaFloat4 fxaaConsolePosPos, +*/ + +// fxaaConsoleRcpFrameOpt: +// Only used on FXAA Console. +// This must be from a constant/uniform. +// This effects sub-pixel AA quality and inversely sharpness. +// Where N ranges between, +// N = 0.50 (default) +// N = 0.33 (sharper) +// {x___} = -N/screenWidthInPixels +// {_y__} = -N/screenHeightInPixels +// {__z_} = N/screenWidthInPixels +// {___w} = N/screenHeightInPixels + +// fxaaConsoleRcpFrameOpt2: +// Only used on FXAA Console. +// Not used on 360, but used on PS3 and PC. +// This must be from a constant/uniform. +// {x___} = -2.0/screenWidthInPixels +// {_y__} = -2.0/screenHeightInPixels +// {__z_} = 2.0/screenWidthInPixels +// {___w} = 2.0/screenHeightInPixels diff --git a/code/nel/src/3d/shaders/fxaa_pp_arbfp1.txt b/code/nel/src/3d/shaders/fxaa_pp_arbfp1.txt new file mode 100644 index 000000000..5a498ed61 --- /dev/null +++ b/code/nel/src/3d/shaders/fxaa_pp_arbfp1.txt @@ -0,0 +1,300 @@ +!!ARBfp1.0 +OPTION ARB_precision_hint_fastest; +# cgc version 3.1.0013, build date Apr 18 2012 +# command line args: -profile arbfp1 -O3 -fastmath -fastprecision +# source file: fxaa_pp.cg +#vendor NVIDIA Corporation +#version 3.1.0.13 +#profile arbfp1 +#program fxaa_pp +#semantic fxaa_pp.fxaaQualityRcpFrame +#semantic fxaa_pp.fxaaQualitySubpix +#semantic fxaa_pp.fxaaQualityEdgeThreshold +#semantic fxaa_pp.fxaaQualityEdgeThresholdMin +#semantic fxaa_pp.nlTex0 : TEX0 +#var float2 pos : $vin.TEXCOORD0 : TEX0 : 0 : 1 +#var float2 fxaaQualityRcpFrame : : c[0] : 1 : 1 +#var float fxaaQualitySubpix : : c[1] : 2 : 1 +#var float fxaaQualityEdgeThreshold : : c[2] : 3 : 1 +#var float fxaaQualityEdgeThresholdMin : : c[3] : 4 : 1 +#var sampler2D nlTex0 : TEX0 : texunit 0 : 5 : 1 +#var float4 oCol : $vout.COLOR : COL : 6 : 1 +#const c[4] = 0 -1 1 -2 +#const c[5] = 2 0.5 0.25 1.5 +#const c[6] = 4 12 0.083333336 3 +PARAM c[7] = { program.local[0..3], + { 0, -1, 1, -2 }, + { 2, 0.5, 0.25, 1.5 }, + { 4, 12, 0.083333336, 3 } }; +TEMP R0; +TEMP R1; +TEMP R2; +TEMP R3; +TEMP R4; +TEMP R5; +TEMP R6; +TEMP R7; +TEMP R8; +TEMP R9; +MOV R3.xyz, c[4]; +MAD R2.zw, R3.xyyz, c[0].xyxy, fragment.texcoord[0].xyxy; +MAD R0.xy, R3, c[0], fragment.texcoord[0]; +MAD R1.xy, R3.zyzw, c[0], fragment.texcoord[0]; +TEX R5.y, R1, texture[0], 2D; +MAD R1.xy, R3.zxzw, c[0], fragment.texcoord[0]; +ADD R0.zw, fragment.texcoord[0].xyxy, -c[0].xyxy; +TEX R4.y, R0.zwzw, texture[0], 2D; +TEX R6.y, R2.zwzw, texture[0], 2D; +TEX R8, fragment.texcoord[0], texture[0], 2D; +TEX R1.y, R1, texture[0], 2D; +TEX R0.y, R0, texture[0], 2D; +ADD R0.z, R4.y, R5.y; +MAD R1.z, R0.y, c[4].w, R0; +MAD R0.zw, R3.xyyx, c[0].xyxy, fragment.texcoord[0].xyxy; +TEX R2.y, R0.zwzw, texture[0], 2D; +ADD R0.x, R2.y, R1.y; +ABS R0.w, R1.z; +ADD R1.zw, fragment.texcoord[0].xyxy, c[0].xyxy; +TEX R7.y, R1.zwzw, texture[0], 2D; +MAD R0.z, R8.y, c[4].w, R0.x; +ABS R0.z, R0; +MAD R2.x, R0.z, c[5], R0.w; +MAD R0.zw, R3.xyxz, c[0].xyxy, fragment.texcoord[0].xyxy; +TEX R3.y, R0.zwzw, texture[0], 2D; +ADD R0.z, R0.y, R3.y; +ADD R1.x, R6.y, R7.y; +MAD R0.w, R3.y, c[4], R1.x; +MAD R1.x, R8.y, c[4].w, R0.z; +ABS R0.w, R0; +ADD R2.x, R0.w, R2; +ADD R2.w, R4.y, R6.y; +ADD R0.w, R5.y, R7.y; +ABS R1.z, R1.x; +MAD R1.x, R1.y, c[4].w, R0.w; +ABS R1.w, R1.x; +MAD R1.x, R2.y, c[4].w, R2.w; +MAD R1.z, R1, c[5].x, R1.w; +ABS R1.x, R1; +ADD R1.x, R1, R1.z; +SGE R4.x, R1, R2; +MAX R1.x, R3.y, R8.y; +MAX R1.z, R1.y, R1.x; +MAX R1.x, R0.y, R2.y; +MAX R1.x, R1, R1.z; +MIN R1.z, R3.y, R8.y; +MIN R1.w, R1.y, R1.z; +MIN R1.z, R0.y, R2.y; +MIN R1.z, R1, R1.w; +MUL R2.x, R1, c[2]; +ADD R3.z, R1.x, -R1; +ABS R3.w, R4.x; +MAX R1.w, R2.x, c[3].x; +ADD R2.z, R3, -R1.w; +CMP R2.x, R2.z, c[4], c[4].z; +CMP R1.x, -R3.w, c[4], c[4].z; +MUL R3.w, R2.x, R1.x; +CMP R1.z, -R3.w, R1.y, R3.y; +ADD R1.y, -R8, R1.z; +CMP R1.w, -R3, R2.y, R0.y; +ADD R0.y, -R8, R1.w; +MUL R4.x, R2, R4; +CMP R3.y, -R3.w, c[0], R3.x; +ABS R4.w, R1.y; +ABS R4.z, R0.y; +SGE R0.y, R4.z, R4.w; +MUL R1.y, R2.x, R0; +ABS R0.y, R0; +CMP R4.y, -R0, c[4].x, c[4].z; +ABS R0.y, R1.x; +CMP R0.y, -R0, c[4].x, c[4].z; +MUL R1.x, R2, R0.y; +CMP R2.y, -R4.x, c[0], c[0].x; +CMP R2.y, -R1, -R2, R2; +MAD R1.y, R2, c[5], fragment.texcoord[0]; +CMP R5.z, -R4.x, R1.y, fragment.texcoord[0].y; +ADD R5.y, R5.z, -R3; +MAD R0.y, R2, c[5], fragment.texcoord[0].x; +CMP R3.x, -R1, c[0], R3; +CMP R6.x, -R3.w, R0.y, fragment.texcoord[0]; +ADD R5.w, R5.z, R3.y; +ADD R1.x, R6, -R3; +MOV R1.y, R5; +TEX R0.y, R1, texture[0], 2D; +MUL R1.y, R2.x, R4; +ADD R0.x, R0.z, R0; +ADD R0.w, R2, R0; +MAD R0.z, R0.x, c[5].x, R0.w; +ADD R1.w, R8.y, R1; +ADD R1.z, R8.y, R1; +CMP R4.y, -R1, R1.z, R1.w; +ADD R1.z, R6.x, R3.x; +MAD R5.x, -R4.y, c[5].y, R0.y; +MOV R1.w, R5; +TEX R0.y, R1.zwzw, texture[0], 2D; +MAX R1.w, R4.z, R4; +MAD R1.y, -R4, c[5], R0; +MUL R4.z, R1.w, c[5]; +ABS R0.y, R1; +SGE R1.w, R0.y, R4.z; +ABS R6.y, R5.x; +SGE R0.y, R6, R4.z; +ABS R1.w, R1; +CMP R6.y, -R1.w, c[4].x, c[4].z; +ABS R0.y, R0; +CMP R5.z, -R0.y, c[4].x, c[4]; +ADD_SAT R0.y, R5.z, R6; +MUL R4.w, R2.x, R0.y; +MUL R0.y, R2.x, R6; +MAD R1.w, R3.y, c[5], R5; +CMP R6.x, -R0.y, R1.w, R5.w; +MAD R6.z, R3.x, c[5].w, R1; +CMP R1.z, -R0.y, R6, R1; +MOV R1.w, R6.x; +TEX R0.y, R1.zwzw, texture[0], 2D; +MUL R1.w, R4, R6.y; +CMP R6.y, -R1.w, R0, R1; +MUL R0.y, R2.x, R5.z; +MAD R1.y, -R3, c[5].w, R5; +CMP R5.w, -R0.y, R1.y, R5.y; +MAD R6.z, -R3.x, c[5].w, R1.x; +CMP R1.x, -R0.y, R6.z, R1; +MOV R1.y, R5.w; +TEX R0.y, R1, texture[0], 2D; +MUL R5.y, R4.w, R5.z; +CMP R0.y, -R5, R0, R5.x; +MAD R5.x, -R4.y, c[5].y, R0.y; +CMP R5.z, -R5.y, R5.x, R0.y; +MAD R1.y, -R4, c[5], R6; +CMP R1.y, -R1.w, R1, R6; +ABS R1.w, R1.y; +SGE R1.w, R1, R4.z; +ABS R0.y, R5.z; +SGE R0.y, R0, R4.z; +ABS R1.w, R1; +CMP R6.y, -R1.w, c[4].x, c[4].z; +ABS R0.y, R0; +CMP R5.y, -R0, c[4].x, c[4].z; +ADD_SAT R0.y, R5, R6; +MUL R5.x, R4.w, R0.y; +MUL R0.y, R4.w, R6; +MAD R1.w, R3.y, c[5].x, R6.x; +CMP R6.x, -R0.y, R1.w, R6; +MAD R6.z, R3.x, c[5].x, R1; +CMP R1.z, -R0.y, R6, R1; +MOV R1.w, R6.x; +TEX R0.y, R1.zwzw, texture[0], 2D; +MUL R1.w, R5.x, R6.y; +CMP R6.y, -R1.w, R0, R1; +MUL R0.y, R4.w, R5; +MAD R1.y, -R3, c[5].x, R5.w; +CMP R4.w, -R0.y, R1.y, R5; +MAD R6.z, -R3.x, c[5].x, R1.x; +CMP R1.x, -R0.y, R6.z, R1; +MOV R1.y, R4.w; +TEX R0.y, R1, texture[0], 2D; +MUL R5.y, R5.x, R5; +CMP R0.y, -R5, R0, R5.z; +MAD R5.z, -R4.y, c[5].y, R0.y; +CMP R5.w, -R5.y, R5.z, R0.y; +MAD R1.y, -R4, c[5], R6; +CMP R1.y, -R1.w, R1, R6; +ABS R1.w, R1.y; +SGE R1.w, R1, R4.z; +ABS R1.w, R1; +CMP R6.y, -R1.w, c[4].x, c[4].z; +ABS R0.y, R5.w; +SGE R0.y, R0, R4.z; +ABS R0.y, R0; +CMP R5.y, -R0, c[4].x, c[4].z; +ADD_SAT R0.y, R5, R6; +MUL R5.z, R5.x, R0.y; +MUL R0.y, R5.x, R6; +MAD R1.w, R3.y, c[6].x, R6.x; +CMP R6.x, -R0.y, R1.w, R6; +MAD R6.z, R3.x, c[6].x, R1; +CMP R1.z, -R0.y, R6, R1; +MOV R1.w, R6.x; +TEX R0.y, R1.zwzw, texture[0], 2D; +MUL R1.w, R5.z, R6.y; +CMP R6.y, -R1.w, R0, R1; +MUL R0.y, R5.x, R5; +MAD R1.y, -R3, c[6].x, R4.w; +CMP R4.w, -R0.y, R1.y, R4; +MAD R5.x, -R3, c[6], R1; +CMP R1.x, -R0.y, R5, R1; +MOV R1.y, R4.w; +TEX R0.y, R1, texture[0], 2D; +MUL R1.y, R5.z, R5; +CMP R5.x, -R1.y, R0.y, R5.w; +MAD R5.y, -R4, c[5], R5.x; +CMP R1.y, -R1, R5, R5.x; +MAD R0.y, -R4, c[5], R6; +CMP R0.y, -R1.w, R0, R6; +ABS R5.x, R0.y; +ABS R1.w, R1.y; +SGE R1.w, R1, R4.z; +SGE R5.x, R5, R4.z; +ABS R4.z, R5.x; +ABS R1.w, R1; +CMP R4.z, -R4, c[4].x, c[4]; +CMP R1.w, -R1, c[4].x, c[4].z; +MUL R4.z, R5, R4; +MAD R5.y, R3.x, c[6], R1.z; +CMP R5.y, -R4.z, R5, R1.z; +MAD R5.x, R3.y, c[6].y, R6; +CMP R1.z, -R4, R5.x, R6.x; +MUL R1.w, R5.z, R1; +ADD R4.z, -fragment.texcoord[0].x, R5.y; +ADD R1.z, -fragment.texcoord[0].y, R1; +CMP R1.z, -R3.w, R1, R4; +MAD R4.z, -R3.x, c[6].y, R1.x; +MAD R3.x, -R3.y, c[6].y, R4.w; +CMP R3.y, -R1.w, R4.z, R1.x; +CMP R1.x, -R1.w, R3, R4.w; +ADD R1.w, fragment.texcoord[0].x, -R3.y; +ADD R1.x, fragment.texcoord[0].y, -R1; +CMP R1.x, -R3.w, R1, R1.w; +SLT R1.w, R1.x, R1.z; +ADD R3.x, R1, R1.z; +ABS R1.w, R1; +MIN R1.x, R1, R1.z; +CMP R1.w, -R1, c[4].x, c[4].z; +MUL R1.z, R2.x, R1.w; +RCP R3.x, R3.x; +MAD R1.x, R1, -R3, c[5].y; +MUL R1.w, R4.y, c[5].y; +SLT R3.x, R1.y, c[4]; +SLT R1.y, R8, R1.w; +SLT R0.y, R0, c[4].x; +ADD R0.y, R0, -R1; +ADD R1.y, -R1, R3.x; +ABS R0.y, R0; +ABS R1.y, R1; +CMP R0.y, -R0, c[4].z, c[4].x; +CMP R1.y, -R1, c[4].z, c[4].x; +CMP R0.x, -R1.z, R0.y, R1.y; +MAD R0.y, R0.z, c[6].z, -R8; +ABS R0.x, R0; +CMP R0.x, -R0, c[4], c[4].z; +MUL R0.x, R2, R0; +CMP R0.x, -R0, c[4], R1; +RCP R0.z, R3.z; +ABS R0.y, R0; +MUL_SAT R0.y, R0, R0.z; +MUL R0.z, R0.y, c[4].w; +ADD R0.z, R0, c[6].w; +MUL R0.y, R0, R0; +MUL R0.y, R0.z, R0; +MUL R0.y, R0, R0; +MUL R0.y, R0, c[1].x; +MAX R0.x, R0, R0.y; +MAD R0.y, R0.x, R2, fragment.texcoord[0]; +MAD R0.z, R0.x, R2.y, fragment.texcoord[0].x; +CMP R0.x, -R3.w, R0.z, fragment.texcoord[0]; +CMP R0.y, -R4.x, R0, fragment.texcoord[0]; +TEX R0.xyz, R0, texture[0], 2D; +CMP R1, R2.z, R8, R9; +MOV R0.w, R8.y; +CMP result.color, -R2.x, R0, R1; +END +# 260 instructions, 10 R-regs diff --git a/code/nel/src/3d/shaders/fxaa_pp_ps_2_0.txt b/code/nel/src/3d/shaders/fxaa_pp_ps_2_0.txt new file mode 100644 index 000000000..de51eba42 --- /dev/null +++ b/code/nel/src/3d/shaders/fxaa_pp_ps_2_0.txt @@ -0,0 +1,306 @@ +ps_2_x +// cgc version 3.1.0013, build date Apr 18 2012 +// command line args: -profile ps_2_x -O3 -fastmath -fastprecision +// source file: fxaa_pp.cg +//vendor NVIDIA Corporation +//version 3.1.0.13 +//profile ps_2_x +//program fxaa_pp +//semantic fxaa_pp.fxaaQualityRcpFrame +//semantic fxaa_pp.fxaaQualitySubpix +//semantic fxaa_pp.fxaaQualityEdgeThreshold +//semantic fxaa_pp.fxaaQualityEdgeThresholdMin +//semantic fxaa_pp.nlTex0 : TEX0 +//var float2 pos : $vin.TEXCOORD0 : TEX0 : 0 : 1 +//var float2 fxaaQualityRcpFrame : : c[0] : 1 : 1 +//var float fxaaQualitySubpix : : c[1] : 2 : 1 +//var float fxaaQualityEdgeThreshold : : c[2] : 3 : 1 +//var float fxaaQualityEdgeThresholdMin : : c[3] : 4 : 1 +//var sampler2D nlTex0 : TEX0 : texunit 0 : 5 : 1 +//var float4 oCol : $vout.COLOR : COL : 6 : 1 +//const c[4] = 0 -1 1 -2 +//const c[5] = 2 0.5 0.25 1.5 +//const c[6] = 4 12 0.083333336 +//const c[7] = -2 3 +dcl_2d s0 +def c4, 0.00000000, -1.00000000, 1.00000000, -2.00000000 +def c5, 2.00000000, 0.50000000, 0.25000000, 1.50000000 +def c6, 4.00000000, 12.00000000, 0.08333334, 0 +def c7, -2.00000000, 3.00000000, 0, 0 +dcl t0.xy +mov r0.zw, c0.xyxy +mad r3.xy, c4.zxzw, r0.zwzw, t0 +texld r7, r3, s0 +texld r1, t0, s0 +mov r0.xy, c0 +mad r0.xy, c4.yxzw, r0, t0 +texld r8, r0, s0 +mov r0.xy, c0 +mad r0.xy, c4, r0, t0 +texld r9, r0, s0 +add r0.xy, t0, -c0 +texld r5, r0, s0 +mov r3.xy, c0 +mad r3.xy, c4.zyzw, r3, t0 +texld r3, r3, s0 +add r7.x, r8.y, r7.y +mad r0.z, r1.y, c4.w, r7.x +add r0.x, r5.y, r3.y +mad r0.w, r9.y, c4, r0.x +mov r0.xy, c0 +mad r0.xy, c4.xzzw, r0, t0 +texld r6, r0, s0 +add r5.x, r9.y, r6.y +abs r0.z, r0 +abs r0.w, r0 +mad r3.x, r0.z, c5, r0.w +mov r0.zw, c0.xyxy +mad r4.xy, c4.yzzw, r0.zwzw, t0 +texld r4, r4, s0 +add r0.xy, t0, c0 +texld r0, r0, s0 +add r4.x, r5.y, r4.y +add r5.y, r3, r0 +add r0.x, r4.y, r0.y +mad r0.x, r6.y, c4.w, r0 +abs r0.x, r0 +add r0.w, r0.x, r3.x +mad r0.x, r8.y, c4.w, r4 +mad r0.z, r7.y, c4.w, r5.y +mad r0.y, r1, c4.w, r5.x +abs r0.z, r0 +abs r0.y, r0 +mad r0.y, r0, c5.x, r0.z +abs r0.x, r0 +add r0.x, r0, r0.y +add r0.x, r0, -r0.w +cmp r3.y, r0.x, c4.z, c4.x +max r0.y, r6, r1 +max r0.z, r7.y, r0.y +max r0.y, r9, r8 +max r0.y, r0, r0.z +min r0.z, r6.y, r1.y +min r0.w, r7.y, r0.z +min r0.z, r9.y, r8.y +min r0.z, r0, r0.w +mul r3.x, r0.y, c2 +abs_pp r0.x, r3.y +add r4.y, r0, -r0.z +max r0.w, r3.x, c3.x +add r4.z, r4.y, -r0.w +cmp_pp r4.w, r4.z, c4.z, c4.x +mul_pp r5.w, r4, r3.y +cmp_pp r0.y, -r0.x, c4.z, c4.x +mul_pp r5.z, r4.w, r0.y +cmp_pp r3.x, -r0, c4, c4.z +cmp r6.w, -r5.z, r6.y, r7.y +cmp r7.w, -r5.z, r9.y, r8.y +add r0.z, -r1.y, r6.w +add r0.y, -r1, r7.w +abs r9.z, r0 +abs r7.y, r0 +add r0.y, r7, -r9.z +cmp r0.y, r0, c4.z, c4.x +max r7.y, r7, r9.z +mul_pp r0.z, r4.w, r0.y +cmp r0.w, -r5, c0.x, c0.y +cmp r6.x, -r0.z, r0.w, -r0.w +mov r0.z, c0.y +cmp r6.y, -r5.z, c4.x, r0.z +mad r0.w, r6.x, c5.y, t0.y +cmp r0.z, -r5.w, t0.y, r0.w +add r8.z, r0, r6.y +add r7.z, r0, -r6.y +mov r9.y, r7.z +mov r8.y, r8.z +mad r0.w, r6.x, c5.y, t0.x +mov r0.x, c0 +mul_pp r3.x, r4.w, r3 +cmp r6.z, -r3.x, c4.x, r0.x +cmp r0.x, -r5.z, t0, r0.w +add r9.x, r0, -r6.z +texld r3, r9, s0 +add r8.x, r0, r6.z +abs_pp r3.x, r0.y +texld r0, r8, s0 +cmp_pp r0.x, -r3, c4.z, c4 +add r0.w, r1.y, r6 +add r0.z, r1.y, r7.w +mul_pp r0.x, r4.w, r0 +cmp r6.w, -r0.x, r0.z, r0 +mad r7.w, -r6, c5.y, r0.y +mad r8.w, -r6, c5.y, r3.y +abs r0.y, r7.w +abs r0.x, r8.w +mad r0.x, -r7.y, c5.z, r0 +mad r0.y, -r7, c5.z, r0 +cmp r0.x, r0, c4.z, c4 +abs_pp r0.x, r0 +cmp_pp r9.z, -r0.x, c4, c4.x +cmp r0.y, r0, c4.z, c4.x +abs_pp r0.y, r0 +cmp_pp r9.w, -r0.y, c4.z, c4.x +mul_pp r0.x, r4.w, r9.z +mad r0.y, -r6, c5.w, r7.z +cmp r7.z, -r0.x, r7, r0.y +mad r0.z, -r6, c5.w, r9.x +cmp r9.x, -r0, r9, r0.z +mov r9.y, r7.z +texld r3, r9, s0 +add_pp_sat r3.z, r9, r9.w +mul_pp r0.x, r4.w, r9.w +mad r0.y, r6, c5.w, r8.z +cmp r3.x, -r0, r8.z, r0.y +mad r0.z, r6, c5.w, r8.x +mul_pp r8.z, r4.w, r3 +cmp r8.x, -r0, r8, r0.z +mov r8.y, r3.x +texld r0, r8, s0 +mul_pp r0.w, r8.z, r9 +cmp r3.z, -r0.w, r7.w, r0.y +mul_pp r0.x, r8.z, r9.z +cmp r0.y, -r0.x, r8.w, r3 +mad r0.z, -r6.w, c5.y, r0.y +cmp r8.w, -r0.x, r0.y, r0.z +mad r3.y, -r6.w, c5, r3.z +cmp r9.w, -r0, r3.z, r3.y +abs r0.y, r9.w +abs r0.x, r8.w +mad r0.y, -r7, c5.z, r0 +mad r0.x, -r7.y, c5.z, r0 +cmp r0.y, r0, c4.z, c4.x +abs_pp r0.y, r0 +cmp_pp r10.x, -r0.y, c4.z, c4 +cmp r0.x, r0, c4.z, c4 +abs_pp r0.x, r0 +cmp_pp r9.z, -r0.x, c4, c4.x +mul_pp r0.x, r8.z, r10 +mad r0.y, r6, c5.x, r3.x +cmp r7.w, -r0.x, r3.x, r0.y +mad r0.z, r6, c5.x, r8.x +cmp r8.x, -r0, r8, r0.z +mov r8.y, r7.w +texld r0, r8, s0 +mul_pp r0.w, r8.z, r9.z +mad r3.x, -r6.z, c5, r9 +mad r0.x, -r6.y, c5, r7.z +cmp r0.x, -r0.w, r7.z, r0 +add_pp_sat r0.z, r9, r10.x +mul_pp r7.z, r8, r0 +cmp r9.x, -r0.w, r9, r3 +mov r9.y, r0.x +texld r3, r9, s0 +mul_pp r0.z, r7, r9 +cmp r0.w, -r0.z, r8, r3.y +mul_pp r3.x, r7.z, r10 +cmp r3.y, -r3.x, r9.w, r0 +mad r0.y, -r6.w, c5, r0.w +cmp r8.z, -r0, r0.w, r0.y +mad r3.z, -r6.w, c5.y, r3.y +cmp r9.z, -r3.x, r3.y, r3 +abs r0.y, r8.z +abs r0.z, r9 +mad r0.y, -r7, c5.z, r0 +mad r0.z, -r7.y, c5, r0 +cmp r0.y, r0, c4.z, c4.x +abs_pp r0.y, r0 +cmp_pp r8.w, -r0.y, c4.z, c4.x +cmp r0.z, r0, c4, c4.x +abs_pp r0.z, r0 +cmp_pp r9.w, -r0.z, c4.z, c4.x +mul_pp r0.y, r7.z, r8.w +mad r0.z, -r6.y, c6.x, r0.x +cmp r10.x, -r0.y, r0, r0.z +mad r0.w, -r6.z, c6.x, r9.x +cmp r9.x, -r0.y, r9, r0.w +mov r9.y, r10.x +texld r3, r9, s0 +mul_pp r0.x, r7.z, r9.w +mad r0.z, r6, c6.x, r8.x +mad r0.y, r6, c6.x, r7.w +cmp r3.x, -r0, r7.w, r0.y +cmp r8.x, -r0, r8, r0.z +mov r8.y, r3.x +texld r0, r8, s0 +add_pp_sat r3.z, r8.w, r9.w +mul_pp r0.x, r7.z, r3.z +mul_pp r3.z, r0.x, r9.w +cmp r0.y, -r3.z, r9.z, r0 +mul_pp r0.z, r0.x, r8.w +cmp r0.w, -r0.z, r8.z, r3.y +mad r3.w, -r6, c5.y, r0.y +cmp r0.y, -r3.z, r0, r3.w +mad r3.y, -r6.w, c5, r0.w +cmp r0.z, -r0, r0.w, r3.y +abs r3.y, r0 +abs r0.w, r0.z +mad r3.y, -r7, c5.z, r3 +mad r0.w, -r7.y, c5.z, r0 +cmp r3.y, r3, c4.z, c4.x +abs_pp r3.y, r3 +cmp r0.w, r0, c4.z, c4.x +cmp_pp r3.z, -r3.y, c4, c4.x +abs_pp r0.w, r0 +cmp_pp r3.y, -r0.w, c4.z, c4.x +mul_pp r0.w, r0.x, r3.z +mul_pp r0.x, r0, r3.y +mad r3.w, r6.y, c6.y, r3.x +cmp r3.x, -r0.w, r3, r3.w +mad r3.z, r6, c6.y, r8.x +cmp r0.w, -r0, r8.x, r3.z +mad r3.y, -r6, c6, r10.x +cmp r3.y, -r0.x, r10.x, r3 +add r3.x, -t0.y, r3 +add r0.w, -t0.x, r0 +cmp r0.w, -r5.z, r0, r3.x +mad r3.x, -r6.z, c6.y, r9 +cmp r0.x, -r0, r9, r3 +add r3.x, t0.y, -r3.y +add r0.x, t0, -r0 +cmp r0.x, -r5.z, r0, r3 +add r3.x, r0, -r0.w +add r3.y, r0.x, r0.w +cmp r3.x, r3, c4, c4.z +abs_pp r3.x, r3 +min r0.x, r0, r0.w +cmp_pp r3.x, -r3, c4.z, c4 +mul_pp r0.w, r4, r3.x +rcp r3.y, r3.y +mad r0.x, r0, -r3.y, c5.y +cmp r3.y, r0, c4.x, c4.z +mad r3.x, -r6.w, c5.y, r1.y +cmp r3.x, r3, c4, c4.z +cmp r0.y, r0.z, c4.x, c4.z +add_pp r0.z, -r3.x, r3.y +add_pp r0.y, r0, -r3.x +abs_pp r0.y, r0 +abs_pp r0.z, r0 +cmp_pp r0.z, -r0, c4.x, c4 +cmp_pp r0.y, -r0, c4.x, c4.z +cmp_pp r0.y, -r0.w, r0, r0.z +abs_pp r0.y, r0 +cmp_pp r0.y, -r0, c4.z, c4.x +mul_pp r0.y, r4.w, r0 +rcp r0.w, r4.y +cmp r0.x, -r0.y, r0, c4 +add r3.y, r4.x, r5 +add r3.x, r5, r7 +mad r3.x, r3, c5, r3.y +mad r0.z, r3.x, c6, -r1.y +abs r0.z, r0 +mul_sat r0.z, r0, r0.w +mul r0.w, r0.z, r0.z +mad r0.z, r0, c7.x, c7.y +mul r0.z, r0, r0.w +mul r0.z, r0, r0 +mul r0.z, r0, c1.x +max r0.x, r0, r0.z +mad r0.y, r0.x, r6.x, t0 +mad r0.z, r0.x, r6.x, t0.x +cmp r0.x, -r5.z, t0, r0.z +cmp r0.y, -r5.w, t0, r0 +texld r0, r0, s0 +mov r0.w, r1.y +cmp r1, r4.z, r2, r1 +cmp r0, -r4.w, r1, r0 +mov oC0, r0 diff --git a/code/nel/src/3d/shaders/fxaa_vp.cg b/code/nel/src/3d/shaders/fxaa_vp.cg new file mode 100644 index 000000000..13c9c9bcb --- /dev/null +++ b/code/nel/src/3d/shaders/fxaa_vp.cg @@ -0,0 +1,20 @@ + +void fxaa_vp( + // Per vertex parameters + float3 position : POSITION, + float2 texCoord0 : TEXCOORD0, + + // Vertex program constants + uniform float4x4 modelViewProjection, + uniform float4 fxaaConsolePosPos, + + // Output position + out float4 oPosition : POSITION, + out float2 oTexCoord0 : TEXCOORD0, + out float4 oTexCoord1 : TEXCOORD1 +) +{ + oPosition = mul(modelViewProjection, float4(position, 0.0)); + oTexCoord0 = texCoord0; + oTexCoord1 = texCoord0.xyxy + fxaaConsolePosPos; +} diff --git a/code/nel/src/3d/shaders/fxaa_vp_arbvp1.txt b/code/nel/src/3d/shaders/fxaa_vp_arbvp1.txt new file mode 100644 index 000000000..6c8530ae0 --- /dev/null +++ b/code/nel/src/3d/shaders/fxaa_vp_arbvp1.txt @@ -0,0 +1,31 @@ +!!ARBvp1.0 +# cgc version 3.1.0013, build date Apr 18 2012 +# command line args: -profile arbvp1 -fastmath -fastprecision +# source file: fxaa_vp.cg +#vendor NVIDIA Corporation +#version 3.1.0.13 +#profile arbvp1 +#program fxaa_vp +#semantic fxaa_vp.modelViewProjection +#semantic fxaa_vp.fxaaConsolePosPos +#var float3 position : $vin.POSITION : POSITION : 0 : 1 +#var float2 texCoord0 : $vin.TEXCOORD0 : TEXCOORD0 : 1 : 1 +#var float4x4 modelViewProjection : : c[1], 4 : 2 : 1 +#var float4 fxaaConsolePosPos : : c[5] : 3 : 1 +#var float4 oPosition : $vout.POSITION : HPOS : 4 : 1 +#var float2 oTexCoord0 : $vout.TEXCOORD0 : TEX0 : 5 : 1 +#var float4 oTexCoord1 : $vout.TEXCOORD1 : TEX1 : 6 : 1 +#const c[0] = 0 +PARAM c[6] = { { 0 }, + program.local[1..5] }; +TEMP R0; +MOV R0.w, c[0].x; +MOV R0.xyz, vertex.position; +DP4 result.position.w, R0, c[4]; +DP4 result.position.z, R0, c[3]; +DP4 result.position.y, R0, c[2]; +DP4 result.position.x, R0, c[1]; +ADD result.texcoord[1], vertex.texcoord[0].xyxy, c[5]; +MOV result.texcoord[0].xy, vertex.texcoord[0]; +END +# 8 instructions, 1 R-regs diff --git a/code/nel/src/3d/shaders/readme.txt b/code/nel/src/3d/shaders/readme.txt new file mode 100644 index 000000000..fe657f6e5 --- /dev/null +++ b/code/nel/src/3d/shaders/readme.txt @@ -0,0 +1,4 @@ +Compiled shaders are embedded in the source. +Must compile and re-embed manually. + +FXAA is in public domain. \ No newline at end of file diff --git a/code/nel/src/3d/stereo_debugger.cpp b/code/nel/src/3d/stereo_debugger.cpp index 34a348c80..6650e1c2b 100644 --- a/code/nel/src/3d/stereo_debugger.cpp +++ b/code/nel/src/3d/stereo_debugger.cpp @@ -26,7 +26,7 @@ */ #if !FINAL_VERSION -#include +#include "std3d.h" #include // STL includes @@ -42,6 +42,7 @@ #include #include #include +#include using namespace std; // using namespace NLMISC; @@ -137,8 +138,6 @@ CStereoDebugger::CStereoDebugger() : m_Driver(NULL), m_Stage(0), m_SubStage(0), CStereoDebugger::~CStereoDebugger() { - releaseTextures(); - if (!m_Mat.empty()) { m_Driver->deleteMaterial(m_Mat); @@ -188,8 +187,6 @@ void CStereoDebugger::setDriver(NL3D::UDriver *driver) if (m_PixelProgram) { - initTextures(); - m_Mat = m_Driver->createMaterial(); m_Mat.initUnlit(); m_Mat.setColor(CRGBA::White); @@ -202,8 +199,6 @@ void CStereoDebugger::setDriver(NL3D::UDriver *driver) mat->setZFunc(CMaterial::always); mat->setDoubleSided(true); - setTextures(); - m_QuadUV.V0 = CVector(0.f, 0.f, 0.5f); m_QuadUV.V1 = CVector(1.f, 0.f, 0.5f); m_QuadUV.V2 = CVector(1.f, 1.f, 0.5f); @@ -216,6 +211,42 @@ void CStereoDebugger::setDriver(NL3D::UDriver *driver) } } +bool CStereoDebugger::attachToDisplay() +{ + return false; +} + +void CStereoDebugger::detachFromDisplay() +{ + +} + +void CStereoDebugger::getTextures() +{ + nlassert(!m_LeftTexU); + nlassert(!m_RightTexU); + uint32 width, height; + m_Driver->getWindowSize(width, height); + m_LeftTexU = m_Driver->getRenderTargetManager().getRenderTarget(width, height); + m_RightTexU = m_Driver->getRenderTargetManager().getRenderTarget(width, height); + NL3D::CMaterial *mat = m_Mat.getObjectPtr(); + mat->setTexture(0, m_LeftTexU->getITexture()); + mat->setTexture(1, m_RightTexU->getITexture()); +} + +void CStereoDebugger::recycleTextures() +{ + nlassert(m_LeftTexU); + nlassert(m_RightTexU); + m_Mat.getObjectPtr()->setTexture(0, NULL); + m_Mat.getObjectPtr()->setTexture(1, NULL); + m_Driver->getRenderTargetManager().recycleRenderTarget(m_LeftTexU); + m_Driver->getRenderTargetManager().recycleRenderTarget(m_RightTexU); + m_LeftTexU = NULL; + m_RightTexU = NULL; +} + +/* void CStereoDebugger::releaseTextures() { if (!m_Mat.empty()) @@ -233,7 +264,7 @@ void CStereoDebugger::releaseTextures() m_RightTexU = NULL; m_RightTex = NULL; // CSmartPtr } - +*//* void CStereoDebugger::initTextures() { uint32 width, height; @@ -261,15 +292,15 @@ void CStereoDebugger::initTextures() drvInternal->setupTexture(*m_RightTex); m_RightTexU = new CTextureUser(m_RightTex); nlassert(!drvInternal->isTextureRectangle(m_RightTex)); // not allowed -} - +}*/ +/* void CStereoDebugger::setTextures() { NL3D::CMaterial *mat = m_Mat.getObjectPtr(); mat->setTexture(0, m_LeftTex); mat->setTexture(1, m_RightTex); -} - +}*/ +/* void CStereoDebugger::verifyTextures() { if (m_Driver) @@ -287,7 +318,7 @@ void CStereoDebugger::verifyTextures() setTextures(); } } -} +}*/ /// Gets the required screen resolution for this device bool CStereoDebugger::getScreenResolution(uint &width, uint &height) @@ -307,6 +338,12 @@ void CStereoDebugger::getClippingFrustum(uint cid, NL3D::UCamera *camera) const // do nothing } +/// Get the original frustum of the camera +void CStereoDebugger::getOriginalFrustum(uint cid, NL3D::UCamera *camera) const +{ + // do nothing, as we never modified it +} + /// Is there a next pass bool CStereoDebugger::nextPass() { @@ -388,6 +425,12 @@ bool CStereoDebugger::wantScene() return m_Stage != 3; } +/// The 3D scene end (after multiple wantScene) +bool CStereoDebugger::wantSceneEffects() +{ + return m_Stage != 3; +} + /// Interface within the 3D scene bool CStereoDebugger::wantInterface3D() { @@ -402,11 +445,22 @@ bool CStereoDebugger::wantInterface2D() return m_Stage == 3; } +bool CStereoDebugger::isSceneFirst() +{ + return m_Stage != 3; +} + +bool CStereoDebugger::isSceneLast() +{ + return m_Stage != 3; +} + /// Returns true if a new render target was set, always fase if not using render targets bool CStereoDebugger::beginRenderTarget() { if (m_Stage != 3 && m_Driver && (m_Driver->getPolygonMode() == UDriver::Filled)) { + if (!m_LeftTexU) getTextures(); if (m_Stage % 2) static_cast(m_Driver)->setRenderTarget(*m_RightTexU, 0, 0, 0, 0); else static_cast(m_Driver)->setRenderTarget(*m_LeftTexU, 0, 0, 0, 0); return true; @@ -430,14 +484,15 @@ bool CStereoDebugger::endRenderTarget() uint32 width, height; NL3D::IDriver *drvInternal = (static_cast(m_Driver))->getDriver(); NL3D::CMaterial *mat = m_Mat.getObjectPtr(); - mat->setTexture(0, m_LeftTex); - mat->setTexture(1, m_RightTex); + mat->setTexture(0, m_LeftTexU->getITexture()); + mat->setTexture(1, m_RightTexU->getITexture()); drvInternal->activePixelProgram(m_PixelProgram); m_Driver->drawQuad(m_QuadUV, m_Mat); drvInternal->activePixelProgram(NULL); m_Driver->enableFog(fogEnabled); + recycleTextures(); return true; } diff --git a/code/nel/src/3d/stereo_display.cpp b/code/nel/src/3d/stereo_display.cpp index eace867fc..2a79c1039 100644 --- a/code/nel/src/3d/stereo_display.cpp +++ b/code/nel/src/3d/stereo_display.cpp @@ -25,7 +25,7 @@ * . */ -#include +#include "std3d.h" #include // STL includes @@ -35,6 +35,7 @@ // Project includes #include +#include #include #include diff --git a/code/nel/src/3d/stereo_hmd.cpp b/code/nel/src/3d/stereo_hmd.cpp index d28017482..25249e2b4 100644 --- a/code/nel/src/3d/stereo_hmd.cpp +++ b/code/nel/src/3d/stereo_hmd.cpp @@ -25,7 +25,7 @@ * . */ -#include +#include "std3d.h" #include // STL includes diff --git a/code/nel/src/3d/stereo_libvr.cpp b/code/nel/src/3d/stereo_libvr.cpp index 44a5a0a5a..c655f959c 100644 --- a/code/nel/src/3d/stereo_libvr.cpp +++ b/code/nel/src/3d/stereo_libvr.cpp @@ -27,7 +27,7 @@ #ifdef HAVE_LIBVR -#include +#include "std3d.h" #include #include diff --git a/code/nel/src/3d/stereo_ovr.cpp b/code/nel/src/3d/stereo_ovr.cpp index 402d9b2d0..073490dc0 100644 --- a/code/nel/src/3d/stereo_ovr.cpp +++ b/code/nel/src/3d/stereo_ovr.cpp @@ -41,15 +41,16 @@ * so, delete this exception statement from your version. */ -#ifdef HAVE_LIBOVR +#ifdef HAVE_LIBOVR_02 -#include +#include "std3d.h" #include // STL includes #include // External includes +#define OVR_NO_STDINT #include // NeL includes @@ -169,7 +170,7 @@ public: OVR::HMDInfo HMDInfo; }; -CStereoOVR::CStereoOVR(const CStereoOVRDeviceHandle *handle) : m_Stage(0), m_SubStage(0), m_OrientationCached(false), m_Driver(NULL), m_BarrelTexU(NULL), m_PixelProgram(NULL), m_EyePosition(0.0f, 0.09f, 0.15f), m_Scale(1.0f) +CStereoOVR::CStereoOVR(const CStereoOVRDeviceHandle *handle) : m_Stage(0), m_SubStage(0), m_OrientationCached(false), m_Driver(NULL), m_SceneTexture(NULL), m_GUITexture(NULL), m_PixelProgram(NULL), m_EyePosition(0.0f, 0.09f, 0.15f), m_Scale(1.0f) { ++s_DeviceCounter; m_DevicePtr = new CStereoOVRDevicePtr(); @@ -213,9 +214,6 @@ CStereoOVR::~CStereoOVR() m_BarrelMat.getObjectPtr()->setTexture(0, NULL); m_Driver->deleteMaterial(m_BarrelMat); } - delete m_BarrelTexU; - m_BarrelTexU = NULL; - m_BarrelTex = NULL; // CSmartPtr delete m_PixelProgram; m_PixelProgram = NULL; @@ -340,7 +338,7 @@ void CStereoOVR::setDriver(NL3D::UDriver *driver) { m_Driver = driver; - m_BarrelTex = new CTextureBloom(); // lol bloom + /*m_BarrelTex = new CTextureBloom(); // lol bloom m_BarrelTex->setRenderTarget(true); m_BarrelTex->setReleasable(false); m_BarrelTex->resize(m_DevicePtr->HMDInfo.HResolution, m_DevicePtr->HMDInfo.VResolution); @@ -348,7 +346,7 @@ void CStereoOVR::setDriver(NL3D::UDriver *driver) m_BarrelTex->setWrapS(ITexture::Clamp); m_BarrelTex->setWrapT(ITexture::Clamp); drvInternal->setupTexture(*m_BarrelTex); - m_BarrelTexU = new CTextureUser(m_BarrelTex); + m_BarrelTexU = new CTextureUser(m_BarrelTex);*/ m_BarrelMat = m_Driver->createMaterial(); m_BarrelMat.initUnlit(); @@ -361,7 +359,7 @@ void CStereoOVR::setDriver(NL3D::UDriver *driver) barrelMat->setZWrite(false); barrelMat->setZFunc(CMaterial::always); barrelMat->setDoubleSided(true); - barrelMat->setTexture(0, m_BarrelTex); + // barrelMat->setTexture(0, m_BarrelTex); m_BarrelQuadLeft.V0 = CVector(0.f, 0.f, 0.5f); m_BarrelQuadLeft.V1 = CVector(0.5f, 0.f, 0.5f); @@ -373,7 +371,7 @@ void CStereoOVR::setDriver(NL3D::UDriver *driver) m_BarrelQuadRight.V2 = CVector(1.f, 1.f, 0.5f); m_BarrelQuadRight.V3 = CVector(0.5f, 1.f, 0.5f); - nlassert(!drvInternal->isTextureRectangle(m_BarrelTex)); // not allowed + // nlassert(!drvInternal->isTextureRectangle(m_BarrelTex)); // not allowed m_BarrelQuadLeft.Uv0 = CUV(0.f, 0.f); m_BarrelQuadLeft.Uv1 = CUV(0.5f, 0.f); @@ -400,6 +398,8 @@ bool CStereoOVR::getScreenResolution(uint &width, uint &height) void CStereoOVR::initCamera(uint cid, const NL3D::UCamera *camera) { + m_OriginalFrustum[cid] = camera->getFrustum(); + float ar = (float)m_DevicePtr->HMDInfo.HResolution / ((float)m_DevicePtr->HMDInfo.VResolution * 2.0f); float fov = 2.0f * atanf((m_DevicePtr->HMDInfo.HScreenSize * 0.5f * 0.5f) / (m_DevicePtr->HMDInfo.EyeToScreenDistance)); //(float)NLMISC::Pi/2.f; // 2.0f * atanf(m_DevicePtr->HMDInfo.VScreenSize / 2.0f * m_DevicePtr->HMDInfo.EyeToScreenDistance); m_LeftFrustum[cid].initPerspective(fov, ar, camera->getFrustum().Near, camera->getFrustum().Far); @@ -427,6 +427,12 @@ void CStereoOVR::getClippingFrustum(uint cid, NL3D::UCamera *camera) const camera->setFrustum(m_ClippingFrustum[cid]); } +/// Get the original frustum of the camera +void CStereoOVR::getOriginalFrustum(uint cid, NL3D::UCamera *camera) const +{ + camera->setFrustum(m_OriginalFrustum[cid]); +} + void CStereoOVR::updateCamera(uint cid, const NL3D::UCamera *camera) { if (camera->getFrustum().Near != m_LeftFrustum[cid].Near @@ -440,53 +446,59 @@ bool CStereoOVR::nextPass() // Do not allow weird stuff. uint32 width, height; m_Driver->getWindowSize(width, height); - nlassert(width == m_DevicePtr->HMDInfo.HResolution); - nlassert(height == m_DevicePtr->HMDInfo.VResolution); + // nlassert(width == m_DevicePtr->HMDInfo.HResolution); + // nlassert(height == m_DevicePtr->HMDInfo.VResolution); if (m_Driver->getPolygonMode() == UDriver::Filled) { - switch (m_Stage) + switch (m_Stage) // Previous stage { case 0: - ++m_Stage; - m_SubStage = 0; - // stage 1: - // (initBloom) - // clear buffer - // draw scene left - return true; - case 1: - ++m_Stage; + m_Stage += 2; m_SubStage = 0; // stage 2: - // draw scene right + // draw interface 2d (onto render target) return true; case 2: ++m_Stage; m_SubStage = 0; // stage 3: - // (endBloom) - // draw interface 3d left + // (initBloom) + // clear buffer + // draw scene left return true; case 3: ++m_Stage; m_SubStage = 0; // stage 4: - // draw interface 3d right + // draw scene right return true; case 4: ++m_Stage; m_SubStage = 0; // stage 5: - // (endInterfacesDisplayBloom) - // draw interface 2d left + // (endBloom) + // draw interface 3d left return true; case 5: ++m_Stage; m_SubStage = 0; // stage 6: - // draw interface 2d right + // draw interface 3d right return true; + /*case 6: + ++m_Stage; + m_SubStage = 0; + // stage 7: + // (endInterfacesDisplayBloom) + // draw interface 2d left + return true; + case 7: + ++m_Stage; + m_SubStage = 0; + // stage 8: + // draw interface 2d right + return true;*/ case 6: m_Stage = 0; m_SubStage = 0; @@ -518,26 +530,30 @@ bool CStereoOVR::nextPass() const NL3D::CViewport &CStereoOVR::getCurrentViewport() const { - if (m_Stage % 2) return m_LeftViewport; + if (m_Stage == 2) return m_RegularViewport; + else if (m_Stage % 2) return m_LeftViewport; else return m_RightViewport; } const NL3D::CFrustum &CStereoOVR::getCurrentFrustum(uint cid) const { - if (m_Stage % 2) return m_LeftFrustum[cid]; + if (m_Stage == 2) return m_OriginalFrustum[cid]; + else if (m_Stage % 2) return m_LeftFrustum[cid]; else return m_RightFrustum[cid]; } void CStereoOVR::getCurrentFrustum(uint cid, NL3D::UCamera *camera) const { - if (m_Stage % 2) camera->setFrustum(m_LeftFrustum[cid]); + if (m_Stage == 2) camera->setFrustum(m_OriginalFrustum[cid]); + else if (m_Stage % 2) camera->setFrustum(m_LeftFrustum[cid]); else camera->setFrustum(m_RightFrustum[cid]); } void CStereoOVR::getCurrentMatrix(uint cid, NL3D::UCamera *camera) const { CMatrix translate; - if (m_Stage % 2) translate.translate(CVector((m_DevicePtr->HMDInfo.InterpupillaryDistance * m_Scale) * -0.5f, 0.f, 0.f)); + if (m_Stage == 2) { } + else if (m_Stage % 2) translate.translate(CVector((m_DevicePtr->HMDInfo.InterpupillaryDistance * m_Scale) * -0.5f, 0.f, 0.f)); else translate.translate(CVector((m_DevicePtr->HMDInfo.InterpupillaryDistance * m_Scale) * 0.5f, 0.f, 0.f)); CMatrix mat = m_CameraMatrix[cid] * translate; if (camera->getTransformMode() == NL3D::UTransformable::RotQuat) @@ -556,7 +572,7 @@ bool CStereoOVR::wantClear() { switch (m_Stage) { - case 1: + case 3: m_SubStage = 1; return true; } @@ -567,8 +583,8 @@ bool CStereoOVR::wantScene() { switch (m_Stage) { - case 1: - case 2: + case 3: + case 4: m_SubStage = 2; return true; } @@ -579,8 +595,8 @@ bool CStereoOVR::wantInterface3D() { switch (m_Stage) { - case 3: - case 4: + case 5: + case 6: m_SubStage = 3; return true; } @@ -591,37 +607,225 @@ bool CStereoOVR::wantInterface2D() { switch (m_Stage) { - case 5: - case 6: + case 2: m_SubStage = 4; return true; } return m_Driver->getPolygonMode() != UDriver::Filled; } - /// Returns non-NULL if a new render target was set bool CStereoOVR::beginRenderTarget() { // render target always set before driver clear // nlassert(m_SubStage <= 1); - if (m_Driver && m_Stage == 1 && (m_Driver->getPolygonMode() == UDriver::Filled)) + + // Set GUI render target + if (m_Driver && m_Stage == 2 && (m_Driver->getPolygonMode() == UDriver::Filled)) { - static_cast(m_Driver)->setRenderTarget(*m_BarrelTexU, 0, 0, 0, 0); + nlassert(!m_GUITexture); + uint32 width, height; + m_Driver->getWindowSize(width, height); + m_GUITexture = m_Driver->getRenderTargetManager().getRenderTarget(width, height, true, UTexture::RGBA8888); + static_cast(m_Driver)->setRenderTarget(*m_GUITexture); + m_Driver->clearBuffers(NLMISC::CRGBA(0, 0, 0, 0)); return true; } + + // Begin 3D scene render target + if (m_Driver && m_Stage == 3 && (m_Driver->getPolygonMode() == UDriver::Filled)) + { + nlassert(!m_SceneTexture); + uint32 width, height; + m_Driver->getWindowSize(width, height); // Temporary limitation, TODO: scaling! + m_SceneTexture = m_Driver->getRenderTargetManager().getRenderTarget(width, height); + static_cast(m_Driver)->setRenderTarget(*m_SceneTexture); + return true; + } + return false; } +void CStereoOVR::setInterfaceMatrix(const NL3D::CMatrix &matrix) +{ + m_InterfaceCameraMatrix = matrix; +} + +void CStereoOVR::renderGUI() +{ + + /*CMatrix mat; + mat.translate(m_InterfaceCameraMatrix.getPos()); + CVector dir = m_InterfaceCameraMatrix.getJ(); + dir.z = 0; + dir.normalize(); + if (dir.y < 0) + mat.rotateZ(float(NLMISC::Pi+asin(dir.x))); + else + mat.rotateZ(float(NLMISC::Pi+NLMISC::Pi-asin(dir.x))); + m_Driver->setModelMatrix(mat);*/ + m_Driver->setModelMatrix(m_InterfaceCameraMatrix); + + { + NLMISC::CLine line(NLMISC::CVector(0, 5, 2), NLMISC::CVector(0, 5, 3)); + + NL3D::UMaterial mat = m_Driver->createMaterial(); + mat.setZWrite(false); + // mat.setZFunc(UMaterial::always); // Not nice! + mat.setDoubleSided(true); + mat.setColor(NLMISC::CRGBA::Red); + mat.setBlend(false); + + m_Driver->drawLine(line, mat); + + m_Driver->deleteMaterial(mat); + } + + { + nlassert(m_GUITexture); + + NLMISC::CQuadUV quad; + + NL3D::UMaterial umat = m_Driver->createMaterial(); + umat.initUnlit(); + umat.setColor(NLMISC::CRGBA::White); + umat.setDoubleSided(true); + umat.setBlend(true); + umat.setAlphaTest(false); + NL3D::CMaterial *mat = umat.getObjectPtr(); + mat->setShader(NL3D::CMaterial::Normal); + mat->setBlendFunc(CMaterial::one, CMaterial::TBlend::invsrcalpha); + mat->setZWrite(false); + // mat->setZFunc(CMaterial::always); // Not nice + mat->setDoubleSided(true); + mat->setTexture(0, m_GUITexture->getITexture()); + + // user options + float scale = 1.0f; + float distance = 1.5f; + float offcenter = 0.75f; + + float height = scale * distance * 2.0f; + + uint32 winw, winh; + m_Driver->getWindowSize(winw, winh); + float width = height * (float)winw / (float)winh; + + float bottom = -(height * 0.5f); + float top = (height * 0.5f); + + NLMISC::CQuadUV quadUV; + quadUV.V0 = CVector(-(width * 0.5f), distance, -(height * 0.5f)); + quadUV.V1 = CVector((width * 0.5f), distance, -(height * 0.5f)); + quadUV.V2 = CVector((width * 0.5f), distance, (height * 0.5f)); + quadUV.V3 = CVector(-(width * 0.5f), distance, (height * 0.5f)); + quadUV.Uv0 = CUV(0.f, 0.f); + quadUV.Uv1 = CUV(1.f, 0.f); + quadUV.Uv2 = CUV(1.f, 1.f); + quadUV.Uv3 = CUV(0.f, 1.f); + + const uint nbQuads = 128; + static CVertexBuffer vb; + static CIndexBuffer ib; + + vb.setVertexFormat(CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag); + vb.setPreferredMemory(CVertexBuffer::RAMVolatile, false); + vb.setNumVertices((nbQuads + 1) * 2); + + { + CVertexBufferReadWrite vba; + vb.lock(vba); + float radius = distance + offcenter; + float relWidth = width / radius; + float quadWidth = relWidth / (float)nbQuads; + for (uint i = 0; i < nbQuads + 1; ++i) + { + uint vi0 = i * 2; + uint vi1 = vi0 + 1; + float lineH = -(relWidth * 0.5f) + quadWidth * (float)i; + float lineUV = (float)i / (float)(nbQuads); + float left = sin(lineH) * radius; + float forward = cos(lineH) * radius; + vba.setVertexCoord(vi0, left, forward - offcenter, bottom); + vba.setTexCoord(vi0, 0, lineUV, 0.0f); + vba.setVertexCoord(vi1, left, forward - offcenter, top); + vba.setTexCoord(vi1, 0, lineUV, 1.0f); + } + } + + ib.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT); + ib.setPreferredMemory(CIndexBuffer::RAMVolatile, false); + ib.setNumIndexes(nbQuads * 6); + + { + CIndexBufferReadWrite iba; + ib.lock(iba); + for (uint i = 0; i < nbQuads; ++i) + { + uint ti0 = i * 2; + uint ti1 = ti0 + 1; + uint bl = ti0; + uint tl = ti0 + 1; + uint br = ti0 + 2; + uint tr = ti0 + 3; + iba.setTri(ti0 * 3, bl, tl, br); + iba.setTri(ti1 * 3, br, tl, tr); + } + } + + IDriver *driver = static_cast(m_Driver)->getDriver(); + // m_Driver->setPolygonMode(UDriver::Line); + driver->activeVertexBuffer(vb); + driver->activeIndexBuffer(ib); + driver->renderTriangles(*umat.getObjectPtr(), 0, nbQuads * 2); //renderRawQuads(umat, 0, 128); + // m_Driver->setPolygonMode(UDriver::Filled); + + // m_Driver->drawQuad(quadUV, umat); + + m_Driver->deleteMaterial(umat); + } +} + /// Returns true if a render target was fully drawn bool CStereoOVR::endRenderTarget() { // after rendering of course // nlassert(m_SubStage > 1); + + // End GUI render target + if (m_Driver && m_Stage == 2 && (m_Driver->getPolygonMode() == UDriver::Filled)) + { + // End GUI render target + nlassert(m_GUITexture); + CTextureUser texNull; + (static_cast(m_Driver))->setRenderTarget(texNull); + } + + // End of 3D Interface pass left + if (m_Driver && m_Stage == 5 && (m_Driver->getPolygonMode() == UDriver::Filled)) + { + // Render 2D GUI in 3D space, assume existing camera is OK + renderGUI(); + } + + // End of 3D Interface pass right + if (m_Driver && m_Stage == 6 && (m_Driver->getPolygonMode() == UDriver::Filled)) + { + // Render 2D GUI in 3D space, assume existing camera is OK + renderGUI(); + + // Recycle render target + m_Driver->getRenderTargetManager().recycleRenderTarget(m_GUITexture); + m_GUITexture = NULL; + } + + // End 3D scene render target if (m_Driver && m_Stage == 6 && (m_Driver->getPolygonMode() == UDriver::Filled)) // set to 4 to turn off distortion of 2d gui { - CTextureUser cu; - (static_cast(m_Driver))->setRenderTarget(cu); + nlassert(m_SceneTexture); + + CTextureUser texNull; + (static_cast(m_Driver))->setRenderTarget(texNull); bool fogEnabled = m_Driver->fogEnabled(); m_Driver->enableFog(false); @@ -632,7 +836,7 @@ bool CStereoOVR::endRenderTarget() m_Driver->getWindowSize(width, height); NL3D::IDriver *drvInternal = (static_cast(m_Driver))->getDriver(); NL3D::CMaterial *barrelMat = m_BarrelMat.getObjectPtr(); - barrelMat->setTexture(0, m_BarrelTex); + barrelMat->setTexture(0, m_SceneTexture->getITexture()); drvInternal->activePixelProgram(m_PixelProgram); @@ -697,8 +901,13 @@ bool CStereoOVR::endRenderTarget() drvInternal->activePixelProgram(NULL); m_Driver->enableFog(fogEnabled); + // Recycle render target + m_Driver->getRenderTargetManager().recycleRenderTarget(m_SceneTexture); + m_SceneTexture = NULL; + return true; } + return false; } diff --git a/code/nel/src/3d/stereo_ovr_04.cpp b/code/nel/src/3d/stereo_ovr_04.cpp new file mode 100644 index 000000000..121855fb8 --- /dev/null +++ b/code/nel/src/3d/stereo_ovr_04.cpp @@ -0,0 +1,1312 @@ +/** + * \file stereo_ovr.cpp + * \brief CStereoOVR + * \date 2014-08-04 16:21GMT + * \author Jan Boon (Kaetemi) + * CStereoOVR + */ + +/* + * Copyright (C) 2014 by authors + * + * This file is part of NL3D. + * NL3D is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * NL3D is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with NL3D. If not, see + * . + * + * Linking this library statically or dynamically with other modules + * is making a combined work based on this library. Thus, the terms + * and conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give + * you permission to link this library with the Oculus SDK to produce + * an executable, regardless of the license terms of the Oculus SDK, + * and distribute linked combinations including the two, provided that + * you also meet the terms and conditions of the license of the Oculus + * SDK. You must obey the GNU General Public License in all respects + * for all of the code used other than the Oculus SDK. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. + */ + +#ifdef HAVE_LIBOVR + +#include "std3d.h" +#include + +// STL includes +#include + +// External includes +#define OVR_NO_STDINT +#include + +// NeL includes +// #include +#include +#include +#include +#include +#include +#include +#include + +// Project includes + +using namespace std; +// using namespace NLMISC; + +namespace NL3D { + +namespace { + +#include "stereo_ovr_04_program.h" + +class CStereoOVRSystem +{ +public: + CStereoOVRSystem() : m_InitOk(false) + { + + } + + ~CStereoOVRSystem() + { + if (m_InitOk) + { + nlwarning("OVR: Not all resources were released before exit"); + Release(); + } + } + + bool Init() + { + if (!m_InitOk) + { + nldebug("OVR: Initialize"); + m_InitOk = ovr_Initialize(); + nlassert(m_InitOk); + } + + return m_InitOk; + } + + void Release() + { + if (m_InitOk) + { + nldebug("OVR: Release"); + ovr_Shutdown(); + m_InitOk = false; + } + } + +private: + bool m_InitOk; + +}; + +CStereoOVRSystem s_StereoOVRSystem; + +sint s_DeviceCounter = 0; +uint s_DetectId = 0; + +} + +class CStereoOVRDeviceFactory : public IStereoDeviceFactory +{ +public: + uint DeviceIndex; + uint DetectId; + + bool DebugDevice; + ovrHmdType DebugDeviceType; + + IStereoDisplay *createDevice() const + { + CStereoOVR *stereo = new CStereoOVR(this); + if (stereo->isDeviceCreated()) + return stereo; + delete stereo; + return NULL; + } +}; + +static NLMISC::CVector2f toTex(NLMISC::CVector2f texCoord, NLMISC::CVector2f uvScaleOffset[2]) +{ + // return(EyeToSourceUVScale * flattened + EyeToSourceUVOffset); + NLMISC::CVector2f vec = NLMISC::CVector2f(texCoord.x * uvScaleOffset[0].x, texCoord.y * uvScaleOffset[0].y) + uvScaleOffset[1]; + // some trial and error voodoo, sorry + vec = (vec + NLMISC::CVector2f(1, 1)) * 0.5f; + vec.y = 1.0f - vec.y; + vec.x = 1.0f - vec.x; + vec.x += 0.5f; + vec.y *= 2.0f; + + vec.x = 1.0f - vec.x; + + return vec; +} + +static float lerp(float f0, float f1, float factor) +{ + return (f1 * factor) + (f0 * (1.0f - factor)); +} + +CStereoOVR::CStereoOVR(const CStereoOVRDeviceFactory *factory) : m_DevicePtr(NULL), m_Stage(0), m_SubStage(0), m_OrientationCached(false), m_Driver(NULL), m_SceneTexture(NULL), m_GUITexture(NULL), m_EyePosition(0.0f, 0.09f, 0.15f), m_Scale(1.0f), m_AttachedDisplay(false) +{ + nlctassert(NL_OVR_EYE_COUNT == ovrEye_Count); + + if (factory->DetectId != s_DetectId) + { + nlwarning("OVR: Previous device info structures become invalid after listing devices"); + return; + } + + m_DebugDevice = factory->DebugDevice; + if (factory->DebugDevice) m_DevicePtr = ovrHmd_CreateDebug(factory->DebugDeviceType); + else m_DevicePtr = ovrHmd_Create(factory->DeviceIndex); + + if (!m_DevicePtr) + { + nlwarning("OVR: Device not created"); + return; + } + + ++s_DeviceCounter; + + // nldebug("OVR: HScreenSize: %f, VScreenSize: %f", m_DevicePtr->HMDInfo.HScreenSize, m_DevicePtr->HMDInfo.VScreenSize); // No more support for physically non-square pixels? + // nldebug("OVR: VScreenCenter: %f", m_DevicePtr->HMDInfo.VScreenCenter); + // nldebug("OVR: EyeToScreenDistance: %f", m_DevicePtr->HMDInfo.EyeToScreenDistance); + // nldebug("OVR: LensSeparationDistance: %f", m_DevicePtr->HMDInfo.LensSeparationDistance); + // nldebug("OVR: InterpupillaryDistance: %f", m_DevicePtr->HMDInfo.InterpupillaryDistance); + nldebug("OVR: Resolution.w: %i, Resolution.h: %i", m_DevicePtr->Resolution.w, m_DevicePtr->Resolution.h); + // nldebug("OVR: DistortionK[0]: %f, DistortionK[1]: %f", m_DevicePtr->HMDInfo.DistortionK[0], m_DevicePtr->HMDInfo.DistortionK[1]); + // nldebug("OVR: DistortionK[2]: %f, DistortionK[3]: %f", m_DevicePtr->HMDInfo.DistortionK[2], m_DevicePtr->HMDInfo.DistortionK[3]); + + if (!ovrHmd_ConfigureTracking(m_DevicePtr, + ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection, // | ovrTrackingCap_Position + ovrTrackingCap_Orientation)) + { + nlwarning("OVR: Cannot configure tracking"); + ovrHmd_Destroy(m_DevicePtr); + m_DevicePtr = NULL; + --s_DeviceCounter; + return; + } + + float nativeWidth = m_DevicePtr->Resolution.w; + float nativeHeight = m_DevicePtr->Resolution.h; + + // get render descriptions for default fov + ovrEyeRenderDesc eyeRenderDesc[ovrEye_Count]; + eyeRenderDesc[ovrEye_Left] = ovrHmd_GetRenderDesc(m_DevicePtr, ovrEye_Left, m_DevicePtr->DefaultEyeFov[ovrEye_Left]); + eyeRenderDesc[ovrEye_Right] = ovrHmd_GetRenderDesc(m_DevicePtr, ovrEye_Right, m_DevicePtr->DefaultEyeFov[ovrEye_Right]); + nldebug("OVR: LEFT DistortedViewport: x: %i, y: %i, w: %i, h: %i", eyeRenderDesc[0].DistortedViewport.Pos.x, eyeRenderDesc[0].DistortedViewport.Pos.y, eyeRenderDesc[0].DistortedViewport.Size.w, eyeRenderDesc[0].DistortedViewport.Size.h); + nldebug("OVR: LEFT PixelsPerTanAngleAtCenter: x: %f, y: %f ", eyeRenderDesc[0].PixelsPerTanAngleAtCenter.x, eyeRenderDesc[0].PixelsPerTanAngleAtCenter.y); + nldebug("OVR: LEFT ViewAdjust: x: %f, y: %f, z: %f ", eyeRenderDesc[0].ViewAdjust.x, eyeRenderDesc[0].ViewAdjust.y, eyeRenderDesc[0].ViewAdjust.z); + nldebug("OVR: RIGHT DistortedViewport: x: %i, y: %i, w: %i, h: %i", eyeRenderDesc[1].DistortedViewport.Pos.x, eyeRenderDesc[1].DistortedViewport.Pos.y, eyeRenderDesc[1].DistortedViewport.Size.w, eyeRenderDesc[1].DistortedViewport.Size.h); + nldebug("OVR: RIGHT PixelsPerTanAngleAtCenter: x: %f, y: %f ", eyeRenderDesc[1].PixelsPerTanAngleAtCenter.x, eyeRenderDesc[1].PixelsPerTanAngleAtCenter.y); + nldebug("OVR: RIGHT ViewAdjust: x: %f, y: %f, z: %f ", eyeRenderDesc[1].ViewAdjust.x, eyeRenderDesc[1].ViewAdjust.y, eyeRenderDesc[1].ViewAdjust.z); + + // 2014/08/04 19:54:25 DBG a60 snowballs_client.exe stereo_ovr_04.cpp 171 NL3D::CStereoOVR::CStereoOVR : OVR: Resolution.w: 1280, Resolution.h: 800 + // 2014/08/04 19:54:25 DBG a60 snowballs_client.exe stereo_ovr_04.cpp 189 NL3D::CStereoOVR::CStereoOVR : OVR: LEFT DistortedViewport: x: 0, y: 0, w: 640, h: 800 + // 2014/08/04 19:54:25 DBG a60 snowballs_client.exe stereo_ovr_04.cpp 190 NL3D::CStereoOVR::CStereoOVR : OVR: LEFT PixelsPerTanAngleAtCenter: x: 363.247864, y: 363.247864 + // 2014/08/04 19:54:25 DBG a60 snowballs_client.exe stereo_ovr_04.cpp 191 NL3D::CStereoOVR::CStereoOVR : OVR: LEFT ViewAdjust: x: 0.031800, y: 0.000000, z: 0.000000 + // 2014/08/04 19:55:46 DBG 2e18 snowballs_client.exe stereo_ovr_04.cpp 192 NL3D::CStereoOVR::CStereoOVR : OVR: RIGHT DistortedViewport: x: 640, y: 0, w: 640, h: 800 + // 2014/08/04 19:55:46 DBG 2e18 snowballs_client.exe stereo_ovr_04.cpp 193 NL3D::CStereoOVR::CStereoOVR : OVR: RIGHT PixelsPerTanAngleAtCenter: x: 363.247864, y: 363.247864 + // 2014/08/04 19:55:46 DBG 2e18 snowballs_client.exe stereo_ovr_04.cpp 194 NL3D::CStereoOVR::CStereoOVR : OVR: RIGHT ViewAdjust: x: -0.031868, y: 0.000000, z: 0.000000 + + // find out the recommended render target size + ovrSizei fovTextureSize[ovrEye_Count]; + fovTextureSize[ovrEye_Left] = ovrHmd_GetFovTextureSize(m_DevicePtr, ovrEye_Left, eyeRenderDesc[ovrEye_Left].Fov, 1.0f); + fovTextureSize[ovrEye_Right] = ovrHmd_GetFovTextureSize(m_DevicePtr, ovrEye_Right, eyeRenderDesc[ovrEye_Right].Fov, 1.0f); + m_RenderTargetWidth = fovTextureSize[ovrEye_Left].w + fovTextureSize[ovrEye_Right].w; + m_RenderTargetHeight = max(fovTextureSize[ovrEye_Left].h, fovTextureSize[ovrEye_Right].h); + nldebug("OVR: RenderTarget: w: %u, h: %u", m_RenderTargetWidth, m_RenderTargetHeight); + + // 2014/08/04 20:22:03 DBG 30e4 snowballs_client.exe stereo_ovr_04.cpp 213 NL3D::CStereoOVR::CStereoOVR : OVR: RenderTarget: w: 2414, h: 1870 // That looks a bit excessive... + + for (uint eye = 0; eye < ovrEye_Count; ++eye) + { + ovrFovPort &fov = eyeRenderDesc[eye].Fov; + + // store data + m_EyeViewAdjustX[eye] = -eyeRenderDesc[eye].ViewAdjust.x; + + // setup viewport + m_EyeViewport[eye].init( + (float)eyeRenderDesc[eye].DistortedViewport.Pos.x / nativeWidth, + (float)eyeRenderDesc[eye].DistortedViewport.Pos.y / nativeHeight, + (float)eyeRenderDesc[eye].DistortedViewport.Size.w / nativeWidth, + (float)eyeRenderDesc[eye].DistortedViewport.Size.h / nativeHeight); + nldebug("OVR: EyeViewport: x: %f, y: %f, w: %f, h: %f", m_EyeViewport[eye].getX(), m_EyeViewport[eye].getY(), m_EyeViewport[eye].getWidth(), m_EyeViewport[eye].getHeight()); + ovrRecti eyeViewport; + eyeViewport.Pos.x = (eyeRenderDesc[eye].DistortedViewport.Pos.x * m_RenderTargetWidth) / m_DevicePtr->Resolution.w; + eyeViewport.Pos.y = (eyeRenderDesc[eye].DistortedViewport.Pos.y * m_RenderTargetHeight) / m_DevicePtr->Resolution.h; + eyeViewport.Size.w = (eyeRenderDesc[eye].DistortedViewport.Size.w * m_RenderTargetWidth) / m_DevicePtr->Resolution.w; + eyeViewport.Size.h = (eyeRenderDesc[eye].DistortedViewport.Size.h * m_RenderTargetHeight) / m_DevicePtr->Resolution.h; + + // calculate hfov and ar + /*float combinedTanHalfFovHorizontal = max(fov.LeftTan, fov.RightTan); + float combinedTanHalfFovVertical = max(fov.UpTan, fov.DownTan); + float horizontalFullFovInRadians = 2.0f * atanf (combinedTanHalfFovHorizontal); + float aspectRatio = combinedTanHalfFovHorizontal / combinedTanHalfFovVertical; + float m_EyeHFov[NL_OVR_EYE_COUNT]; + float m_EyeAR[NL_OVR_EYE_COUNT]; + m_EyeHFov[eye] = horizontalFullFovInRadians; + m_EyeAR[eye] = aspectRatio; + nldebug("OVR: HFOV: %f, AR: %f", horizontalFullFovInRadians, aspectRatio); + m_EyeFrustumBase[eye].initPerspective(m_EyeHFov[eye], m_EyeAR[eye], 1.0f, 100.f); + nldebug("OVR: FOV: Left: %f, Right: %f, Down: %f, Up: %f", // DOUBLE CHECK + m_EyeFrustumBase[eye].Left, m_EyeFrustumBase[eye].Right, m_EyeFrustumBase[eye].Bottom, m_EyeFrustumBase[eye].Top);*/ + m_EyeFrustumBase[eye].init( + -fov.LeftTan, // OVR provides positive values + fov.RightTan, // DEBUG: If renders shifted left and right, swap left and right + -fov.DownTan, + fov.UpTan, // DEBUG: If renders shifted up or down, swap down and up + 1.0f, // dummy + 100.f, // dummy + true); + nldebug("OVR: FOV: Left: %f, Right: %f, Down: %f, Up: %f", + m_EyeFrustumBase[eye].Left, m_EyeFrustumBase[eye].Right, m_EyeFrustumBase[eye].Bottom, m_EyeFrustumBase[eye].Top); + + // get distortion mesh + ovrDistortionMesh meshData; + ovrHmd_CreateDistortionMesh(m_DevicePtr, (ovrEyeType)eye, fov, + ovrDistortionCap_Chromatic /*| ovrDistortionCap_TimeWarp*/ | ovrDistortionCap_Vignette, // I believe the timewarp gimmick screws with parallax + &meshData); + ovrVector2f uvScaleOffset[2]; + + // get parameters for programs + ovrHmd_GetRenderScaleAndOffset(fov, + fovTextureSize[eye], eyeViewport, + (ovrVector2f *)uvScaleOffset); + m_EyeUVScaleOffset[eye][0] = NLMISC::CVector2f(uvScaleOffset[0].x, uvScaleOffset[0].y); + m_EyeUVScaleOffset[eye][1] = NLMISC::CVector2f(uvScaleOffset[1].x, uvScaleOffset[1].y); + + // chroma bugfix + float chromaFactor = 1.00f; + if (m_DevicePtr->Type == ovrHmd_DK2) + chromaFactor = 0.75f; + + // create distortion mesh vertex buffer + m_VB[eye].setVertexFormat(CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag | CVertexBuffer::TexCoord1Flag | CVertexBuffer::TexCoord2Flag | CVertexBuffer::PrimaryColorFlag); + m_VB[eye].setPreferredMemory(CVertexBuffer::StaticPreferred, true); + m_VB[eye].setNumVertices(meshData.VertexCount); + { + CVertexBufferReadWrite vba; + m_VB[eye].lock(vba); + for (uint i = 0; i < meshData.VertexCount; ++i) + { + ovrDistortionVertex &ov = meshData.pVertexData[i]; + vba.setVertexCoord(i, (ov.ScreenPosNDC.x + 1.0f) * 0.5f, (ov.ScreenPosNDC.y + 1.0f) * 0.5f, 0.5f); + NLMISC::CVector2f texR( + lerp(ov.TanEyeAnglesG.x, ov.TanEyeAnglesR.x, chromaFactor), + lerp(ov.TanEyeAnglesG.y, ov.TanEyeAnglesR.y, chromaFactor)); + NLMISC::CVector2f texG(ov.TanEyeAnglesG.x, ov.TanEyeAnglesG.y); + NLMISC::CVector2f texB( + lerp(ov.TanEyeAnglesG.x, ov.TanEyeAnglesB.x, chromaFactor), + lerp(ov.TanEyeAnglesG.y, ov.TanEyeAnglesB.y, chromaFactor)); + texR = toTex(texR, m_EyeUVScaleOffset[eye]); + texG = toTex(texG, m_EyeUVScaleOffset[eye]); + texB = toTex(texB, m_EyeUVScaleOffset[eye]); + vba.setTexCoord(i, 0, texR.x, texR.y); + vba.setTexCoord(i, 1, texG.x, texG.y); + vba.setTexCoord(i, 2, texB.x, texB.y); + NLMISC::CRGBA color; + color.R = color.G = color.B = (uint8)(ov.VignetteFactor * 255.99f); + color.A = 255; // (uint8)(ov.TimeWarpFactor * 255.99f); + vba.setColor(i, color); + } + } + + // create distortion mesh index buffer + m_IB[eye].setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT); + m_IB[eye].setPreferredMemory(CIndexBuffer::StaticPreferred, true); + m_IB[eye].setNumIndexes(meshData.IndexCount); + { + CIndexBufferReadWrite iba; + m_IB[eye].lock(iba); + for (uint i = 0; i + 2 < meshData.IndexCount; i += 3) + { + nlassert(meshData.pIndexData[i] < meshData.VertexCount); + nlassert(meshData.pIndexData[i + 1] < meshData.VertexCount); + nlassert(meshData.pIndexData[i + 2] < meshData.VertexCount); + iba.setTri(i, meshData.pIndexData[i], meshData.pIndexData[i + 1], meshData.pIndexData[i + 2]); + } + } + + // set tri count + m_NbTris[eye] = meshData.IndexCount / 3; + + // destroy ovr distortion mesh + ovrHmd_DestroyDistortionMesh(&meshData); + } + + // 2014/08/04 20:22:03 DBG 30e4 snowballs_client.exe stereo_ovr_04.cpp 222 NL3D::CStereoOVR::CStereoOVR : OVR: EyeViewport: x: 0.000000, y: 0.000000, w: 0.500000, h: 1.000000 + // 2014/08/04 22:28:39 DBG 3040 snowballs_client.exe stereo_ovr_04.cpp 235 NL3D::CStereoOVR::CStereoOVR : OVR: HFOV: 2.339905, AR: 0.916641 + // 2014/08/04 20:22:03 DBG 30e4 snowballs_client.exe stereo_ovr_04.cpp 222 NL3D::CStereoOVR::CStereoOVR : OVR: EyeViewport: x: 0.500000, y: 0.000000, w: 0.500000, h: 1.000000 + // 2014/08/04 22:28:39 DBG 3040 snowballs_client.exe stereo_ovr_04.cpp 235 NL3D::CStereoOVR::CStereoOVR : OVR: HFOV: 2.339905, AR: 0.916641 + + ovrHmd_RecenterPose(m_DevicePtr); + + // DEBUG EARLY EXIT + /*nldebug("OVR: Early exit"); + ovrHmd_Destroy(m_DevicePtr); + m_DevicePtr = NULL; + --s_DeviceCounter;*/ +} + +CStereoOVR::~CStereoOVR() +{ + if (m_AttachedDisplay) + { + detachFromDisplay(); + } + + if (!m_UnlitMat.empty()) + { + m_Driver->deleteMaterial(m_UnlitMat); + } + + m_Driver = NULL; + + if (m_DevicePtr) + { + ovrHmd_Destroy(m_DevicePtr); + m_DevicePtr = NULL; + --s_DeviceCounter; + } +} + +void CStereoOVR::setDriver(NL3D::UDriver *driver) +{ + m_Driver = driver; + + CDriverUser *dru = static_cast(driver); + IDriver *drv = dru->getDriver(); + + m_UnlitMat = m_Driver->createMaterial(); + m_UnlitMat.initUnlit(); + m_UnlitMat.setColor(CRGBA::White); + m_UnlitMat.setBlend (false); + m_UnlitMat.setAlphaTest (false); + NL3D::CMaterial *unlitMat = m_UnlitMat.getObjectPtr(); + unlitMat->setShader(NL3D::CMaterial::Normal); + unlitMat->setBlendFunc(CMaterial::one, CMaterial::zero); + unlitMat->setZWrite(false); + unlitMat->setZFunc(CMaterial::always); + unlitMat->setDoubleSided(true); + + unlitMat->texConstantColor(0, NLMISC::CRGBA(255, 0, 0, 0)); + unlitMat->texConstantColor(1, NLMISC::CRGBA(0, 255, 0, 0)); + unlitMat->texConstantColor(2, NLMISC::CRGBA(0, 0, 255, 0)); + + m_UnlitMat.texEnvArg0RGB(0, UMaterial::Texture, UMaterial::SrcColor); + m_UnlitMat.texEnvArg1RGB(0, UMaterial::Constant, UMaterial::SrcColor); + m_UnlitMat.texEnvOpRGB(0, UMaterial::Modulate); + + m_UnlitMat.texEnvArg0RGB(1, UMaterial::Texture, UMaterial::SrcColor); + m_UnlitMat.texEnvArg1RGB(1, UMaterial::Constant, UMaterial::SrcColor); + m_UnlitMat.texEnvArg2RGB(1, UMaterial::Previous, UMaterial::SrcColor); + m_UnlitMat.texEnvOpRGB(1, UMaterial::Mad); + + m_UnlitMat.texEnvArg0RGB(2, UMaterial::Texture, UMaterial::SrcColor); + m_UnlitMat.texEnvArg1RGB(2, UMaterial::Constant, UMaterial::SrcColor); + m_UnlitMat.texEnvArg2RGB(2, UMaterial::Previous, UMaterial::SrcColor); + m_UnlitMat.texEnvOpRGB(2, UMaterial::Mad); + + m_UnlitMat.texEnvArg0RGB(3, UMaterial::Previous, UMaterial::SrcColor); + m_UnlitMat.texEnvArg1RGB(3, UMaterial::Diffuse, UMaterial::SrcColor); + m_UnlitMat.texEnvOpRGB(3, UMaterial::Modulate); +} + +bool CStereoOVR::getScreenResolution(uint &width, uint &height) +{ + if (m_DevicePtr) + { + width = m_DevicePtr->Resolution.w; + height = m_DevicePtr->Resolution.h; + return true; + } + return false; +} + +bool CStereoOVR::attachToDisplay() +{ + nldebug("OVR: Attach to display '%s'", m_DevicePtr->DisplayDeviceName); + + if (m_DebugDevice) + return false; + + if (!m_AttachedDisplay) + { + m_Driver->getCurrentScreenMode(m_OriginalMode); + m_Driver->getWindowPos(m_OriginalWinPosX, m_OriginalWinPosY); + } + +#if defined(NL_OS_WINDOWS) + if ((m_DevicePtr->HmdCaps & ovrHmdCap_ExtendDesktop) != ovrHmdCap_ExtendDesktop) + { + nldebug("OVR: Direct Rift"); + CDriverUser *dru = static_cast(m_Driver); + IDriver *drv = dru->getDriver(); + m_AttachedDisplay = ovrHmd_AttachToWindow(m_DevicePtr, (void *)drv->getDisplay(), NULL, NULL); + if (!m_AttachedDisplay) + nlwarning("OVR: Direct Rift failed!"); + } + else +#endif + { + nldebug("OVR: Extended Rift"); + UDriver::CMode mode; + mode.DisplayDevice = m_DevicePtr->DisplayDeviceName; + mode.Windowed = false; + mode.Width = m_DevicePtr->Resolution.w; + mode.Height = m_DevicePtr->Resolution.h; + m_Driver->setMode(mode); + m_AttachedDisplay = true; + } + + return m_AttachedDisplay; +} + +void CStereoOVR::detachFromDisplay() +{ + /*if (!m_OriginalMode.Windowed) + { + m_OriginalMode.Windowed = true; + m_Driver->setMode(m_OriginalMode); + m_OriginalMode.Windowed = false; + }*/ + m_Driver->setMode(m_OriginalMode); + m_Driver->setWindowPos(m_OriginalWinPosX, m_OriginalWinPosY); + m_AttachedDisplay = false; +} + +void CStereoOVR::initCamera(uint cid, const NL3D::UCamera *camera) +{ + m_OriginalFrustum[cid] = camera->getFrustum(); + + /*m_LeftFrustum[cid] = m_OriginalFrustum[cid]; + m_RightFrustum[cid] = m_OriginalFrustum[cid]; + m_ClippingFrustum[cid] = m_OriginalFrustum[cid]; + return;*/ + + m_LeftFrustum[cid].init( + m_EyeFrustumBase[ovrEye_Left].Left * camera->getFrustum().Near, + m_EyeFrustumBase[ovrEye_Left].Right * camera->getFrustum().Near, + m_EyeFrustumBase[ovrEye_Left].Bottom * camera->getFrustum().Near, + m_EyeFrustumBase[ovrEye_Left].Top * camera->getFrustum().Near, + camera->getFrustum().Near, + camera->getFrustum().Far, + true); + + m_RightFrustum[cid].init( + m_EyeFrustumBase[ovrEye_Right].Left * camera->getFrustum().Near, + m_EyeFrustumBase[ovrEye_Right].Right * camera->getFrustum().Near, + m_EyeFrustumBase[ovrEye_Right].Bottom * camera->getFrustum().Near, + m_EyeFrustumBase[ovrEye_Right].Top * camera->getFrustum().Near, + camera->getFrustum().Near, + camera->getFrustum().Far, + true); + + m_ClippingFrustum[cid].init( + min(m_EyeFrustumBase[ovrEye_Left].Left, m_EyeFrustumBase[ovrEye_Right].Left) * camera->getFrustum().Near, + max(m_EyeFrustumBase[ovrEye_Left].Right, m_EyeFrustumBase[ovrEye_Right].Right) * camera->getFrustum().Near, + min(m_EyeFrustumBase[ovrEye_Left].Bottom, m_EyeFrustumBase[ovrEye_Right].Bottom) * camera->getFrustum().Near, + max(m_EyeFrustumBase[ovrEye_Left].Top, m_EyeFrustumBase[ovrEye_Right].Top) * camera->getFrustum().Near, + camera->getFrustum().Near, + camera->getFrustum().Far, + true); +} + +/// Get the frustum to use for clipping +void CStereoOVR::getClippingFrustum(uint cid, NL3D::UCamera *camera) const +{ + camera->setFrustum(m_ClippingFrustum[cid]); +} + +/// Get the original frustum of the camera +void CStereoOVR::getOriginalFrustum(uint cid, NL3D::UCamera *camera) const +{ + camera->setFrustum(m_OriginalFrustum[cid]); +} + +void CStereoOVR::updateCamera(uint cid, const NL3D::UCamera *camera) +{ + if (camera->getFrustum().Near != m_LeftFrustum[cid].Near + || camera->getFrustum().Far != m_LeftFrustum[cid].Far) + CStereoOVR::initCamera(cid, camera); + m_CameraMatrix[cid] = camera->getMatrix(); +} + +bool CStereoOVR::nextPass() +{ + if (m_Driver->getPolygonMode() == UDriver::Filled) + { + switch (m_Stage) // Previous stage + { + case 0: + m_Stage += 2; + m_SubStage = 0; + // stage 2: + // draw interface 2d (onto render target) + return true; + case 2: + ++m_Stage; + m_SubStage = 0; + // stage 3: + // (initBloom) + // clear buffer + // draw scene left + return true; + case 3: + ++m_Stage; + m_SubStage = 0; + // stage 4: + // draw scene right + return true; + case 4: + ++m_Stage; + m_SubStage = 0; + // stage 5: + // (endBloom) + // draw interface 3d left + return true; + case 5: + ++m_Stage; + m_SubStage = 0; + // stage 6: + // draw interface 3d right + return true; + /*case 6: + ++m_Stage; + m_SubStage = 0; + // stage 7: + // (endInterfacesDisplayBloom) + // draw interface 2d left + return true; + case 7: + ++m_Stage; + m_SubStage = 0; + // stage 8: + // draw interface 2d right + return true;*/ + case 6: + m_Stage = 0; + m_SubStage = 0; + // present + m_OrientationCached = false; + return false; + } + } + else + { + switch (m_Stage) + { + case 0: + ++m_Stage; + m_SubStage = 0; + return true; + case 1: + m_Stage = 0; + m_SubStage = 0; + return false; + } + } + nlerror("Invalid stage"); + m_Stage = 0; + m_SubStage = 0; + m_OrientationCached = false; + return false; +} + +const NL3D::CViewport &CStereoOVR::getCurrentViewport() const +{ + if (m_Stage == 2) return m_RegularViewport; + else if (m_Stage % 2) return m_EyeViewport[ovrEye_Left]; + else return m_EyeViewport[ovrEye_Right]; +} + +const NL3D::CFrustum &CStereoOVR::getCurrentFrustum(uint cid) const +{ + if (m_Stage == 2) return m_OriginalFrustum[cid]; + else if (m_Stage % 2) return m_LeftFrustum[cid]; + else return m_RightFrustum[cid]; +} + +void CStereoOVR::getCurrentFrustum(uint cid, NL3D::UCamera *camera) const +{ + if (m_Stage == 2) camera->setFrustum(m_OriginalFrustum[cid]); + else if (m_Stage % 2) camera->setFrustum(m_LeftFrustum[cid]); + else camera->setFrustum(m_RightFrustum[cid]); +} + +void CStereoOVR::getCurrentMatrix(uint cid, NL3D::UCamera *camera) const +{ + CMatrix translate; + if (m_Stage == 2) { } + else if (m_Stage % 2) translate.translate(CVector(m_EyeViewAdjustX[ovrEye_Left] * m_Scale, 0.f, 0.f)); // ok + else translate.translate(CVector(m_EyeViewAdjustX[ovrEye_Right] * m_Scale, 0.f, 0.f)); // ok + CMatrix mat = m_CameraMatrix[cid] * translate; + if (camera->getTransformMode() == NL3D::UTransformable::RotQuat) + { + camera->setPos(mat.getPos()); + camera->setRotQuat(mat.getRot()); + } + else + { + // camera->setTransformMode(NL3D::UTransformable::DirectMatrix); + camera->setMatrix(mat); + } +} + +bool CStereoOVR::wantClear() +{ + switch (m_Stage) + { + case 3: + m_SubStage = 1; + return true; + } + return m_Driver->getPolygonMode() != UDriver::Filled; +} + +bool CStereoOVR::wantScene() +{ + switch (m_Stage) + { + case 3: + case 4: + m_SubStage = 2; + return true; + } + return m_Driver->getPolygonMode() != UDriver::Filled; +} + +bool CStereoOVR::wantSceneEffects() +{ + switch (m_Stage) + { + case 4: + return true; + } + return m_Driver->getPolygonMode() != UDriver::Filled; +} + +bool CStereoOVR::wantInterface3D() +{ + switch (m_Stage) + { + case 5: + case 6: + m_SubStage = 3; + return true; + } + return m_Driver->getPolygonMode() != UDriver::Filled; +} + +bool CStereoOVR::wantInterface2D() +{ + switch (m_Stage) + { + case 2: + m_SubStage = 4; + return true; + } + return m_Driver->getPolygonMode() != UDriver::Filled; +} + +bool CStereoOVR::isSceneFirst() +{ + switch (m_Stage) + { + case 3: + return true; + case 4: + return false; + } + return m_Driver->getPolygonMode() != UDriver::Filled; +} + +bool CStereoOVR::isSceneLast() +{ + switch (m_Stage) + { + case 3: + return false; + case 4: + return true; + } + return m_Driver->getPolygonMode() != UDriver::Filled; +} + +/// Returns non-NULL if a new render target was set +bool CStereoOVR::beginRenderTarget() +{ + // render target always set before driver clear + // nlassert(m_SubStage <= 1); + + // Set GUI render target + if (m_Driver && m_Stage == 2 && (m_Driver->getPolygonMode() == UDriver::Filled)) + { + nlassert(!m_GUITexture); + uint32 width, height; + m_Driver->getWindowSize(width, height); + m_GUITexture = m_Driver->getRenderTargetManager().getRenderTarget(width, height, true, UTexture::RGBA8888); + static_cast(m_Driver)->setRenderTarget(*m_GUITexture); + m_Driver->clearBuffers(NLMISC::CRGBA(0, 0, 0, 0)); + return true; + } + + // Begin 3D scene render target + if (m_Driver && m_Stage == 3 && (m_Driver->getPolygonMode() == UDriver::Filled)) + { + nlassert(!m_SceneTexture); + m_SceneTexture = m_Driver->getRenderTargetManager().getRenderTarget(m_RenderTargetWidth, m_RenderTargetHeight); + static_cast(m_Driver)->setRenderTarget(*m_SceneTexture); + return true; + /*nldebug("OVR: Begin render target");*/ + //m_Driver->beginDefaultRenderTarget(m_RenderTargetWidth, m_RenderTargetHeight); // DEBUG + //return true; + } + + return false; +} + +void CStereoOVR::setInterfaceMatrix(const NL3D::CMatrix &matrix) +{ + m_InterfaceCameraMatrix = matrix; +} + +void CStereoOVR::renderGUI() +{ + m_Driver->setModelMatrix(m_InterfaceCameraMatrix); +/* + { + NLMISC::CLine line(NLMISC::CVector(0, 5, 2), NLMISC::CVector(0, 5, 3)); + + NL3D::UMaterial mat = m_Driver->createMaterial(); + mat.setZWrite(false); + // mat.setZFunc(UMaterial::always); // Not nice! + mat.setDoubleSided(true); + mat.setColor(NLMISC::CRGBA::Red); + mat.setBlend(false); + + m_Driver->drawLine(line, mat); + + m_Driver->deleteMaterial(mat); + } + + { + NL3D::UMaterial mat = m_Driver->createMaterial(); + mat.setZWrite(false); + mat.setZFunc(UMaterial::always); // Not nice! + mat.setDoubleSided(true); + mat.setBlend(false); + NLMISC::CLine line; + + mat.setColor(NLMISC::CRGBA::Red); + line = NLMISC::CLine(NLMISC::CVector(0, 3, -3), NLMISC::CVector(0, 3, 3)); // YPos + m_Driver->drawLine(line, mat); + + mat.setColor(NLMISC::CRGBA::Green); + line = NLMISC::CLine(NLMISC::CVector(3, 0, -3), NLMISC::CVector(3, 0, 3)); // XPos + m_Driver->drawLine(line, mat); + + mat.setColor(NLMISC::CRGBA::Magenta); + line = NLMISC::CLine(NLMISC::CVector(0, -3, -3), NLMISC::CVector(0, -3, 3)); // YNeg + m_Driver->drawLine(line, mat); + + mat.setColor(NLMISC::CRGBA::Cyan); + line = NLMISC::CLine(NLMISC::CVector(-3, 0, -3), NLMISC::CVector(-3, 0, 3)); // XNeg + m_Driver->drawLine(line, mat); + + mat.setColor(NLMISC::CRGBA::Blue); + line = NLMISC::CLine(NLMISC::CVector(0, -3, 3), NLMISC::CVector(0, 3, 3)); // ZPos + m_Driver->drawLine(line, mat); + + mat.setColor(NLMISC::CRGBA::Blue); + line = NLMISC::CLine(NLMISC::CVector(0, -3, -3), NLMISC::CVector(0, 3, -3)); // ZNeg + m_Driver->drawLine(line, mat); + + m_Driver->deleteMaterial(mat); + } + */ + { + nlassert(m_GUITexture); + + NLMISC::CQuadUV quad; + + NL3D::UMaterial umat = m_Driver->createMaterial(); + umat.initUnlit(); + umat.setColor(NLMISC::CRGBA::White); + umat.setDoubleSided(true); + umat.setBlend(true); + umat.setAlphaTest(false); + NL3D::CMaterial *mat = umat.getObjectPtr(); + mat->setShader(NL3D::CMaterial::Normal); + mat->setBlendFunc(CMaterial::one, CMaterial::invsrcalpha); + mat->setZWrite(false); + // mat->setZFunc(CMaterial::always); // Not nice + mat->setDoubleSided(true); + mat->setTexture(0, m_GUITexture->getITexture()); + + // user options + float scale = 1.0f; + float distance = 1.5f; + float offcenter = 0.75f; + + float height = scale * distance * 2.0f; + + uint32 winw, winh; + m_Driver->getWindowSize(winw, winh); + float width = height * (float)winw / (float)winh; + + float bottom = -(height * 0.5f); + float top = (height * 0.5f); + + NLMISC::CQuadUV quadUV; + quadUV.V0 = CVector(-(width * 0.5f), distance, -(height * 0.5f)); + quadUV.V1 = CVector((width * 0.5f), distance, -(height * 0.5f)); + quadUV.V2 = CVector((width * 0.5f), distance, (height * 0.5f)); + quadUV.V3 = CVector(-(width * 0.5f), distance, (height * 0.5f)); + quadUV.Uv0 = CUV(0.f, 0.f); + quadUV.Uv1 = CUV(1.f, 0.f); + quadUV.Uv2 = CUV(1.f, 1.f); + quadUV.Uv3 = CUV(0.f, 1.f); + + const uint nbQuads = 128; + static CVertexBuffer vb; + static CIndexBuffer ib; + + vb.setVertexFormat(CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag); + vb.setPreferredMemory(CVertexBuffer::RAMVolatile, false); + vb.setNumVertices((nbQuads + 1) * 2); + + { + CVertexBufferReadWrite vba; + vb.lock(vba); + float radius = distance + offcenter; + float relWidth = width / radius; + float quadWidth = relWidth / (float)nbQuads; + for (uint i = 0; i < nbQuads + 1; ++i) + { + uint vi0 = i * 2; + uint vi1 = vi0 + 1; + float lineH = -(relWidth * 0.5f) + quadWidth * (float)i; + float lineUV = (float)i / (float)(nbQuads); + float left = sin(lineH) * radius; + float forward = cos(lineH) * radius; + vba.setVertexCoord(vi0, left, forward - offcenter, bottom); + vba.setTexCoord(vi0, 0, lineUV, 0.0f); + vba.setVertexCoord(vi1, left, forward - offcenter, top); + vba.setTexCoord(vi1, 0, lineUV, 1.0f); + } + } + + ib.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT); + ib.setPreferredMemory(CIndexBuffer::RAMVolatile, false); + ib.setNumIndexes(nbQuads * 6); + + { + CIndexBufferReadWrite iba; + ib.lock(iba); + for (uint i = 0; i < nbQuads; ++i) + { + uint ti0 = i * 2; + uint ti1 = ti0 + 1; + uint bl = ti0; + uint tl = ti0 + 1; + uint br = ti0 + 2; + uint tr = ti0 + 3; + iba.setTri(ti0 * 3, bl, tl, br); + iba.setTri(ti1 * 3, br, tl, tr); + } + } + + IDriver *driver = static_cast(m_Driver)->getDriver(); + // m_Driver->setPolygonMode(UDriver::Line); + driver->activeVertexBuffer(vb); + driver->activeIndexBuffer(ib); + driver->renderTriangles(*umat.getObjectPtr(), 0, nbQuads * 2); //renderRawQuads(umat, 0, 128); + // m_Driver->setPolygonMode(UDriver::Filled); + + // m_Driver->drawQuad(quadUV, umat); + + m_Driver->deleteMaterial(umat); + + /*{ + // nldebug("Render GUI lines"); + NL3D::UMaterial rmat = m_Driver->createMaterial(); + rmat.setZWrite(false); + rmat.setZFunc(UMaterial::always); // Not nice! + rmat.setDoubleSided(true); + rmat.setColor(NLMISC::CRGBA::Red); + rmat.setBlend(false); + + m_Driver->setPolygonMode(UDriver::Line); + driver->activeVertexBuffer(vb); + driver->activeIndexBuffer(ib); + driver->renderTriangles(*rmat.getObjectPtr(), 0, nbQuads * 2); + m_Driver->setPolygonMode(UDriver::Filled); + + m_Driver->deleteMaterial(rmat); + }*/ + } +} + +/// Returns true if a render target was fully drawn +bool CStereoOVR::endRenderTarget() +{ + // after rendering of course + // nlassert(m_SubStage > 1); + + // End GUI render target + if (m_Driver && m_Stage == 2 && (m_Driver->getPolygonMode() == UDriver::Filled)) + { + // End GUI render target + nlassert(m_GUITexture); + CTextureUser texNull; + (static_cast(m_Driver))->setRenderTarget(texNull); + } + + // End of 3D Interface pass left + if (m_Driver && m_Stage == 5 && (m_Driver->getPolygonMode() == UDriver::Filled)) + { + // Render 2D GUI in 3D space, assume existing camera is OK + renderGUI(); + } + + // End of 3D Interface pass right + if (m_Driver && m_Stage == 6 && (m_Driver->getPolygonMode() == UDriver::Filled)) + { + // Render 2D GUI in 3D space, assume existing camera is OK + renderGUI(); + + // Recycle render target + m_Driver->getRenderTargetManager().recycleRenderTarget(m_GUITexture); + m_GUITexture = NULL; + } + + // End 3D scene render target + if (m_Driver && m_Stage == 6 && (m_Driver->getPolygonMode() == UDriver::Filled)) + { + nlassert(m_SceneTexture); + + //nldebug("OVR: End render target"); + // m_Driver->endDefaultRenderTarget(NULL); // DEBUG + + // end render target + CTextureUser texNull; + (static_cast(m_Driver))->setRenderTarget(texNull); + + // backup + bool fogEnabled = m_Driver->fogEnabled(); + m_Driver->enableFog(false); + + // must clear everything to black (can we get a mesh to only handle the parts outside of the distortion mesh?) + m_Driver->clearRGBABuffer(CRGBA(0, 0, 0, 255)); + + CDriverUser *dru = static_cast(m_Driver); + IDriver *drv = dru->getDriver(); + + // set matrix mode + CViewport vp; + m_Driver->setViewport(vp); + m_Driver->setMatrixMode2D11(); + + for (uint eye = 0; eye < ovrEye_Count; ++eye) + { + CMaterial *mat = m_UnlitMat.getObjectPtr(); + mat->setTexture(0, m_SceneTexture->getITexture()); + mat->setTexture(1, m_SceneTexture->getITexture()); + mat->setTexture(2, m_SceneTexture->getITexture()); + mat->setTexture(3, m_SceneTexture->getITexture()); + + //m_Driver->setPolygonMode(UDriver::Line); + drv->activeVertexBuffer(m_VB[eye]); + drv->activeIndexBuffer(m_IB[eye]); + drv->renderTriangles(*mat, 0, m_NbTris[eye]); + //m_Driver->setPolygonMode(UDriver::Filled); + + mat->setTexture(0, NULL); + mat->setTexture(1, NULL); + mat->setTexture(2, NULL); + mat->setTexture(3, NULL); + } + + // restore + m_Driver->enableFog(fogEnabled); + + // recycle render target + m_Driver->getRenderTargetManager().recycleRenderTarget(m_SceneTexture); + m_SceneTexture = NULL; + + return true; + } + + /*if (m_Driver && m_Stage == 6 && (m_Driver->getPolygonMode() == UDriver::Filled)) // set to 4 to turn off distortion of 2d gui + { + nlassert(m_SceneTexture); + + CTextureUser texNull; + (static_cast(m_Driver))->setRenderTarget(texNull); + bool fogEnabled = m_Driver->fogEnabled(); + m_Driver->enableFog(false); + + m_Driver->setMatrixMode2D11(); + CViewport vp = CViewport(); + m_Driver->setViewport(vp); + uint32 width, height; + m_Driver->getWindowSize(width, height); + NL3D::IDriver *drvInternal = (static_cast(m_Driver))->getDriver(); + NL3D::CMaterial *barrelMat = m_BarrelMat.getObjectPtr(); + barrelMat->setTexture(0, m_SceneTexture->getITexture()); + + drvInternal->activePixelProgram(m_PixelProgram); + + float w = float(m_BarrelQuadLeft.V1.x),// / float(width), + h = float(m_BarrelQuadLeft.V2.y),// / float(height), + x = float(m_BarrelQuadLeft.V0.x),/// / float(width), + y = float(m_BarrelQuadLeft.V0.y);// / float(height); + + float lensOffset = m_DevicePtr->HMDInfo.LensSeparationDistance * 0.5f; + float lensShift = m_DevicePtr->HMDInfo.HScreenSize * 0.25f - lensOffset; + float lensViewportShift = 4.0f * lensShift / m_DevicePtr->HMDInfo.HScreenSize; + + float lensCenterX = x + (w + lensViewportShift * 0.5f) * 0.5f; + float lensCenterY = y + h * 0.5f; + float screenCenterX = x + w * 0.5f; + float screenCenterY = y + h * 0.5f; + float scaleX = (w / 2); + float scaleY = (h / 2); + float scaleInX = (2 / w); + float scaleInY = (2 / h); + + + drvInternal->setUniform2f(IDriver::PixelProgram, + m_PixelProgram->ovrIndices().LensCenter, + lensCenterX, lensCenterY); + + drvInternal->setUniform2f(IDriver::PixelProgram, + m_PixelProgram->ovrIndices().ScreenCenter, + screenCenterX, screenCenterY); + + drvInternal->setUniform2f(IDriver::PixelProgram, + m_PixelProgram->ovrIndices().Scale, + scaleX, scaleY); + + drvInternal->setUniform2f(IDriver::PixelProgram, + m_PixelProgram->ovrIndices().ScaleIn, + scaleInX, scaleInY); + + + drvInternal->setUniform4fv(IDriver::PixelProgram, + m_PixelProgram->ovrIndices().HmdWarpParam, + 1, m_DevicePtr->HMDInfo.DistortionK); + + m_Driver->drawQuad(m_BarrelQuadLeft, m_BarrelMat); + + x = w; + lensCenterX = x + (w - lensViewportShift * 0.5f) * 0.5f; + screenCenterX = x + w * 0.5f; + + + drvInternal->setUniform2f(IDriver::PixelProgram, + m_PixelProgram->ovrIndices().LensCenter, + lensCenterX, lensCenterY); + + drvInternal->setUniform2f(IDriver::PixelProgram, + m_PixelProgram->ovrIndices().ScreenCenter, + screenCenterX, screenCenterY); + + + m_Driver->drawQuad(m_BarrelQuadRight, m_BarrelMat); + + drvInternal->activePixelProgram(NULL); + m_Driver->enableFog(fogEnabled); + + // Recycle render target + m_Driver->getRenderTargetManager().recycleRenderTarget(m_SceneTexture); + m_SceneTexture = NULL; + + return true; + }*/ + + return false; +} + +NLMISC::CQuat CStereoOVR::getOrientation() const +{ + // broken + + /*NLMISC::CQuat quat; + quat.identity(); + return quat;*/ + + if (m_OrientationCached) + return m_OrientationCache; + + ovrTrackingState ts = ovrHmd_GetTrackingState(m_DevicePtr, ovr_GetTimeInSeconds()); // TODO: Predict forward + if (ts.StatusFlags & ovrStatus_OrientationTracked) + { + // get just the orientation + ovrQuatf quatovr = ts.HeadPose.ThePose.Orientation; + NLMISC::CMatrix coordsys; + float csys[] = { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, -1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, + }; + coordsys.set(csys); + NLMISC::CMatrix matovr; + matovr.setRot(NLMISC::CQuat(quatovr.x, quatovr.y, quatovr.z, quatovr.w)); + NLMISC::CMatrix matr; + // matr.rotateZ(NLMISC::Pi); // uncomment when backwards ... + matr.rotateX(NLMISC::Pi * 0.5f); // fix this properly... :) (note: removing this allows you to use rift while lying down) + NLMISC::CMatrix matnel = matr * matovr * coordsys; + NLMISC::CQuat finalquat = matnel.getRot(); + m_OrientationCache = finalquat; + m_OrientationCached = true; + return finalquat; + } + else + { + if (!m_DebugDevice) + nlwarning("OVR: No orientation returned"); + // return old orientation + m_OrientationCached = true; + return m_OrientationCache; + } +} + +/// Get GUI shift +void CStereoOVR::getInterface2DShift(uint cid, float &x, float &y, float distance) const +{ + +} + +void CStereoOVR::setEyePosition(const NLMISC::CVector &v) +{ + m_EyePosition = v; +} + +const NLMISC::CVector &CStereoOVR::getEyePosition() const +{ + return m_EyePosition; +} + +void CStereoOVR::setScale(float s) +{ + m_EyePosition = m_EyePosition * (s / m_Scale); + m_Scale = s; +} + + + +void CStereoOVR::listDevices(std::vector &devicesOut) +{ + if (!s_StereoOVRSystem.Init()) + return; + + ++s_DetectId; + uint hmdDetect = ovrHmd_Detect(); + nldebug("OVR: Detected %u HMDs", hmdDetect); + + for (uint i = 0; i < hmdDetect; ++i) + { + devicesOut.resize(devicesOut.size() + 1); + CStereoDeviceInfo &deviceInfoOut = devicesOut[devicesOut.size() - 1]; + ovrHmd hmd = ovrHmd_Create(i); + CStereoOVRDeviceFactory *factory = new CStereoOVRDeviceFactory(); + factory->DetectId = s_DetectId; + factory->DeviceIndex = i; + factory->DebugDevice = false; + deviceInfoOut.Factory = factory; + deviceInfoOut.Class = CStereoDeviceInfo::StereoHMD; + deviceInfoOut.Library = CStereoDeviceInfo::OVR; + deviceInfoOut.Manufacturer = hmd->Manufacturer; + deviceInfoOut.ProductName = hmd->ProductName; + deviceInfoOut.AllowAuto = true; + deviceInfoOut.Serial = hmd->SerialNumber; + ovrHmd_Destroy(hmd); + } + +#if !FINAL_VERSION + // Debug DK1 + { + devicesOut.resize(devicesOut.size() + 1); + CStereoDeviceInfo &deviceInfoOut = devicesOut[devicesOut.size() - 1]; + ovrHmd hmd = ovrHmd_CreateDebug(ovrHmd_DK1); + CStereoOVRDeviceFactory *factory = new CStereoOVRDeviceFactory(); + factory->DetectId = s_DetectId; + factory->DebugDevice = true; + factory->DebugDeviceType = ovrHmd_DK1; + deviceInfoOut.Factory = factory; + deviceInfoOut.Class = CStereoDeviceInfo::StereoHMD; + deviceInfoOut.Library = CStereoDeviceInfo::OVR; + deviceInfoOut.Manufacturer = hmd->Manufacturer; + deviceInfoOut.ProductName = hmd->ProductName; + deviceInfoOut.AllowAuto = false; + deviceInfoOut.Serial = "OVR-DK1-DEBUG"; + ovrHmd_Destroy(hmd); + } + // Debug DK2 + { + devicesOut.resize(devicesOut.size() + 1); + CStereoDeviceInfo &deviceInfoOut = devicesOut[devicesOut.size() - 1]; + ovrHmd hmd = ovrHmd_CreateDebug(ovrHmd_DK2); + CStereoOVRDeviceFactory *factory = new CStereoOVRDeviceFactory(); + factory->DetectId = s_DetectId; + factory->DebugDevice = true; + factory->DebugDeviceType = ovrHmd_DK2; + deviceInfoOut.Factory = factory; + deviceInfoOut.Class = CStereoDeviceInfo::StereoHMD; + deviceInfoOut.Library = CStereoDeviceInfo::OVR; + deviceInfoOut.Manufacturer = hmd->Manufacturer; + deviceInfoOut.ProductName = hmd->ProductName; + deviceInfoOut.AllowAuto = false; + deviceInfoOut.Serial = "OVR-DK2-DEBUG"; + ovrHmd_Destroy(hmd); + } +#endif +} + +bool CStereoOVR::isLibraryInUse() +{ + nlassert(s_DeviceCounter >= 0); + return s_DeviceCounter > 0; +} + +void CStereoOVR::releaseLibrary() +{ + nlassert(s_DeviceCounter == 0); + s_StereoOVRSystem.Release(); +} + +bool CStereoOVR::isDeviceCreated() +{ + return m_DevicePtr != NULL; +} + +} /* namespace NL3D */ + +#endif /* HAVE_LIBOVR */ + +/* end of file */ diff --git a/code/nel/src/3d/stereo_ovr_04_program.h b/code/nel/src/3d/stereo_ovr_04_program.h new file mode 100644 index 000000000..f8c253aeb --- /dev/null +++ b/code/nel/src/3d/stereo_ovr_04_program.h @@ -0,0 +1,4 @@ + +// TODO + +/* end of file */ diff --git a/code/nel/src/3d/stereo_ovr_fp.cpp b/code/nel/src/3d/stereo_ovr_fp.cpp index 940be0bfe..84a74598e 100644 --- a/code/nel/src/3d/stereo_ovr_fp.cpp +++ b/code/nel/src/3d/stereo_ovr_fp.cpp @@ -21,6 +21,8 @@ limitations under the License. ************************************************************************************/ +#include "std3d.h" + namespace NL3D { const char *g_StereoOVR_fp40 = "!!ARBfp1.0\n" diff --git a/code/nel/src/misc/di_event_emitter.cpp b/code/nel/src/misc/di_event_emitter.cpp deleted file mode 100644 index 8f41f6453..000000000 --- a/code/nel/src/misc/di_event_emitter.cpp +++ /dev/null @@ -1,354 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "stdmisc.h" - -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/events.h" -#include "nel/misc/win_event_emitter.h" -// -#include "di_mouse_device.h" -#include "di_keyboard_device.h" -#include "di_game_device.h" - - -#ifdef NL_OS_WINDOWS - -#ifdef DEBUG_NEW - #define new DEBUG_NEW -#endif - -namespace NLMISC -{ - -static const char DirectInputLibName[] = "dinput8.dll"; - -///////////////////////////////// -// CDIEventEmitter statics // -///////////////////////////////// - -HMODULE CDIEventEmitter::_DirectInputLibHandle = 0; -CDIEventEmitter::TPDirectInput8Create CDIEventEmitter::_PDirectInput8Create = NULL; -uint CDIEventEmitter::_NumCreatedInterfaces = 0; - -/////////////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////// -// CDIEventEmitter implementation // -//////////////////////////////////// - - -//====================================================== -CDIEventEmitter::CDIEventEmitter(HWND hwnd, CWinEventEmitter *we) -: - _hWnd(hwnd), - _WE(we), - _DInput8(NULL), - _Keyboard(NULL), - _Mouse(NULL), - _ButtonsFlags(noButton) -{ -} -//====================================================== -CDIEventEmitter::~CDIEventEmitter() -{ - releaseMouse(); - releaseKeyboard(); - // release all devices - while (_DeviceServer.getNumDevices() != 0) - { - IInputDevice *dev = _DeviceServer.getDevice(0); - _DeviceServer.removeDevice(dev); - delete dev; - } - if (_DInput8) _DInput8->Release(); - -- _NumCreatedInterfaces; - if (_NumCreatedInterfaces == 0) unloadLib(); -} - -//====================================================== -CDIEventEmitter *CDIEventEmitter::create(HINSTANCE hinst, HWND hwnd, CWinEventEmitter *we) throw(EDirectInput) -{ - if (!loadLib()) throw EDirectInputLibNotFound(); - std::auto_ptr dxee(new CDIEventEmitter(hwnd, we)); - HRESULT result = _PDirectInput8Create(hinst, - DIRECTINPUT_VERSION, - IID_IDirectInput8A, - (void **) &dxee->_DInput8, - NULL); - if (result != DI_OK) throw EDirectInputInitFailed(); - - // ok, everything's fine, commit changes - ++_NumCreatedInterfaces; - return dxee.release(); -} - - -//====================================================== -bool CDIEventEmitter::loadLib() -{ - if (_DirectInputLibHandle != 0) return true; // library already loaded ? - HMODULE handle = ::LoadLibrary(DirectInputLibName); - if (handle == 0) return false; - // try to get the creation function - TPDirectInput8Create cf = (TPDirectInput8Create) ::GetProcAddress(handle, "DirectInput8Create"); - if (!cf) - { - ::FreeLibrary(handle); - return false; - } - // commit changes - _DirectInputLibHandle = handle; - _PDirectInput8Create = cf; - return true; -} - - -//====================================================== -void CDIEventEmitter::unloadLib() -{ - nlassert(_DirectInputLibHandle != 0); - ::FreeLibrary(_DirectInputLibHandle); - _DirectInputLibHandle = 0; - _PDirectInput8Create = NULL; -} - -//====================================================== -void CDIEventEmitter::poll(CEventServer *server) -{ - if (_WE) _ButtonsFlags = _WE->buildFlags(); - if (!server) - server=&_InternalServer; - _DeviceServer.poll(server); -} - - -//====================================================== -TMouseButton CDIEventEmitter::buildButtonsFlags() const -{ - uint mouseFlags; - uint keybFlags; - // - if (_Mouse) // takes the flags from the direct input mouse - { - mouseFlags = (_Mouse->getButton(0) ? leftButton : 0) - | (_Mouse->getButton(1) ? rightButton : 0) - | (_Mouse->getButton(2) ? middleButton : 0); - } - else // takes the flags from the system mouse - { - mouseFlags = _ButtonsFlags & (leftButton | rightButton | middleButton); - } - // - if (_Keyboard) // takes the flags from the direct input keyboard - { - keybFlags = (_Keyboard->ShiftPressed ? shiftButton : 0) - | (_Keyboard->AltPressed ? altButton : 0) - | (_Keyboard->CtrlPressed ? ctrlButton : 0); - } - else // takes the flags from the system keyboard - { - keybFlags = _ButtonsFlags & (shiftButton | altButton | ctrlButton); - } - return (TMouseButton) (keybFlags | mouseFlags); -} - -//====================================================== -IMouseDevice *CDIEventEmitter::getMouseDevice(bool hardware) throw(EInputDevice) -{ - if (_Mouse) return _Mouse; // already created ? - try - { - // Create a mouse - std::auto_ptr mouse(CDIMouse::createMouseDevice(_DInput8, _hWnd, this, hardware, _WE)); - // register to the device server - _DeviceServer.registerDevice(mouse.get()); - _Mouse = mouse.get(); - return mouse.release(); - } - catch (...) - { - if (_WE) _WE->enableMouseEvents(true); - throw; - } -} - -//====================================================== -void CDIEventEmitter::releaseMouse() -{ - if (!_Mouse) return; - // reupdate the system keyboard flags - if (_WE) - { - _WE->resetButtonFlagState(); - _WE->enableMouseEvents(true); - } - // remove the device - _DeviceServer.removeDevice(_Mouse); - delete _Mouse; - _Mouse = NULL; -} - -//=========================================================================== -IKeyboardDevice *CDIEventEmitter::getKeyboardDevice() throw(EInputDevice) -{ - if (_Keyboard) return _Keyboard; - try - { - // create a keyboard - std::auto_ptr keyboard(CDIKeyboard::createKeyboardDevice(_DInput8, _hWnd, this, _WE)); - // register to the device server - _DeviceServer.registerDevice(keyboard.get()); - _Keyboard = keyboard.get(); - return keyboard.release(); - } - catch (...) - { - if (_WE) _WE->enableKeyboardEvents(true); - throw; - } -} - -//========================================================================== -void CDIEventEmitter::releaseKeyboard() -{ - if (!_Keyboard) return; - // reupdate the system keyboard flags - if (_WE) - { - _WE->resetButtonFlagState(); - _WE->enableKeyboardEvents(true); - } - // - _DeviceServer.removeDevice(_Keyboard); - delete _Keyboard; - _Keyboard = NULL; -} - - -//========================================================================== -void CDIEventEmitter::submitEvents(CEventServer &server, bool allWindows) -{ - _InternalServer.setServer(&server); - _InternalServer.pump(allWindows); -} - -//========================================================================== -void CDIEventEmitter::emulateMouseRawMode(bool enable) -{ - nlerror("no raw mode emulation on windows, the CDIMouse has a real raw mode"); -} - -//========================================================================== -/// Tool fct to retrieve the game devices. -static BOOL CALLBACK DIEnumDevicesDescCallback -( - LPCDIDEVICEINSTANCE lpddi, - LPVOID pvRef -) -{ - CGameDeviceDesc desc; - desc.InstanceName = lpddi->tszInstanceName; - desc.ProductName = lpddi->tszProductName; - switch (lpddi->wUsage & 0xff) - { - case DI8DEVTYPE_JOYSTICK: desc.DevType = CGameDeviceDesc::Joystick; break; - case DI8DEVTYPE_GAMEPAD: desc.DevType = CGameDeviceDesc::GamePad; break; - default: desc.DevType = CGameDeviceDesc::DontKnow; break; - } - TDeviceDescVect *dv = (TDeviceDescVect *) pvRef; - dv->push_back(desc); - return DIENUM_CONTINUE; -} - - -//========================================================================== -/// Tool fct to retrieve the game devices GUID -static BOOL CALLBACK DIEnumDevicesGUIDCallback -( - LPCDIDEVICEINSTANCE lpddi, - LPVOID pvRef -) -{ - std::vector *gv = (std::vector *) pvRef; - gv->push_back(lpddi->guidInstance); - return DIENUM_CONTINUE; -} - - -//========================================================================== -void CDIEventEmitter::enumerateGameDevice(TDeviceDescVect &descs) throw(EInputDevice) -{ - uint k; - nlassert(_DInput8); - descs.clear(); - // enum all devices of interest - _DInput8->EnumDevices(DI8DEVCLASS_GAMECTRL, &DIEnumDevicesDescCallback, (LPVOID) &descs, DIEDFL_ALLDEVICES); - for (k = 0; k < descs.size(); ++k) descs[k].Connected = false; - // enum all connected devices - static TDeviceDescVect connecteds; - _DInput8->EnumDevices(DI8DEVCLASS_GAMECTRL, &DIEnumDevicesDescCallback, (LPVOID) &connecteds, DIEDFL_ATTACHEDONLY); - // see which devices are connected - for (k = 0; k < connecteds.size(); ++k) - { - TDeviceDescVect::iterator it = std::find(descs.begin(), descs.end(), connecteds[k]); - it->Connected = true; - } -} - -//========================================================================== -IGameDevice *CDIEventEmitter::createGameDevice(const std::string &instanceName) throw(EInputDevice) -{ - static TDeviceDescVect deviceDescs; - static std::vector deviceGUID; - - nlassert(_DInput8); - enumerateGameDevice(deviceDescs); - // get the ID for each device - deviceGUID.clear(); - HRESULT r = _DInput8->EnumDevices(DI8DEVCLASS_GAMECTRL, &DIEnumDevicesGUIDCallback, (LPVOID) &deviceGUID, DIEDFL_ALLDEVICES); - nlassert(r == DI_OK); - nlassert(deviceDescs.size() == deviceGUID.size()); - - // search the device that match the instance name - for (uint k = 0; k < deviceDescs.size(); ++k) - { - if (deviceDescs[k].InstanceName == instanceName) - { - std::auto_ptr gd(CDIGameDevice::createGameDevice(_DInput8, _hWnd, this, deviceDescs[k], deviceGUID[k])); - // insert in the device server - _DeviceServer.registerDevice(gd.get()); - return gd.release(); - } - } - return NULL; -} - -//========================================================================== -void CDIEventEmitter::releaseGameDevice(IGameDevice *gd) -{ - nlassert(gd); - CDIGameDevice *digd = safe_cast(gd); - _DeviceServer.removeDevice(digd); - delete gd; -} - - -} // NLMISC - -#endif // NL_OS_WINDOWS diff --git a/code/nel/src/misc/di_game_device.cpp b/code/nel/src/misc/di_game_device.cpp deleted file mode 100644 index 5adfb4b9b..000000000 --- a/code/nel/src/misc/di_game_device.cpp +++ /dev/null @@ -1,523 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "stdmisc.h" -#include "di_game_device.h" -#include "nel/misc/game_device_events.h" - -#ifdef NL_OS_WINDOWS - -#ifdef DEBUG_NEW - #define new DEBUG_NEW -#endif - -namespace NLMISC -{ - -//============================================================================ -CDIGameDevice::CDIGameDevice() : _Device(NULL) -{ - ::memset(&_CurrentState, 0, sizeof(_CurrentState)); -} - -//============================================================================ -CDIGameDevice::~CDIGameDevice() -{ - if (_Device) - { - _Device->Unacquire(); - _Device->Release(); - } -} - -//============================================================================ -CDIGameDevice *CDIGameDevice::createGameDevice(IDirectInput8 *di8, - HWND hwnd, - CDIEventEmitter *diEventEmitter, - const CGameDeviceDesc &desc, - REFGUID rguid) throw(EDirectInput) -{ - nlassert(diEventEmitter); - nlassert(di8); - std::auto_ptr dev(new CDIGameDevice); - // - - HRESULT r = di8->CreateDevice(rguid, &dev->_Device, NULL); - if (r != DI_OK) throw EDirectInputGameDeviceNotCreated(); - - r = dev->_Device->SetDataFormat(pJoyDataFormat); - nlassert(r == DI_OK); - // - r = dev->_Device->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); - if (r != DI_OK) throw EDirectInputCooperativeLevelFailed(); - // - // - dev->_Desc = desc; - dev->_EventEmitter = diEventEmitter; - dev->querryControls(); - return dev.release(); -} - -//============================================================================ -void CDIGameDevice::begin(CEventServer *server) -{ - nlassert(_Device); - HRESULT r; - r = _Device->Poll(); - if (r == DIERR_INPUTLOST || r == DIERR_NOTACQUIRED) - { - r = _Device->Acquire(); - if (r != DI_OK) return; - r = _Device->Poll(); - if (r != DI_OK) return; - } - - CDIJoyState newState; - r = _Device->GetDeviceState(sizeof(CDIJoyState), &newState); - if (r != DI_OK) return; - - uint k; - ////////// - // Axis // - ////////// - for (k = 0; k < MaxNumAxis; ++k) - { - CAxis &axis = _Axis[k]; - if (axis.Present) - { - - if (((LONG *) &newState)[k] != ((LONG *) &_CurrentState)[k]) // state changed ? - { - // update position - axis.Value = 2.f * (((LONG *) &newState)[k] - axis.Min) / (float) (axis.Max - axis.Min) - 1.f; - // create event - CGDAxisMoved *event = new CGDAxisMoved((IGameDevice::TAxis) k, axis.Value, this, _EventEmitter); - // update state - ((LONG *) &_CurrentState)[k] = ((LONG *) &newState)[k]; - // - server->postEvent(event); - // - } - } - } - - - ///////////// - // Buttons // - ///////////// - for (k = 0; k < _Buttons.size(); ++k) - { - CButton &bt = _Buttons[k]; - if ((newState.rgbButtons[k] & 0x80) != (_CurrentState.rgbButtons[k] & 0x80)) - { - bool pushed = (newState.rgbButtons[k] & 0x80) != 0; - // update the state of the button - bt.Pushed = pushed; - CGDButton *event; - if (pushed) event = new CGDButtonDown(k, this, _EventEmitter); - else event = new CGDButtonUp(k, this, _EventEmitter); - // update state - _CurrentState.rgbButtons[k] = newState.rgbButtons[k]; - server->postEvent(event); - } - } - - ///////////// - // Sliders // - ///////////// - for (k = 0; k < _Sliders.size(); ++k) - { - CSlider &sl = _Sliders[k]; - if (newState.rglSlider[k] != _CurrentState.rglSlider[k]) // state changed ? - { - // update position - sl.Pos = ( newState.rglSlider[k] - sl.Min) / (float) (sl.Max - sl.Min); - // create event - CGDSliderMoved *event = new CGDSliderMoved(sl.Pos, k, this, _EventEmitter); - // update state - _CurrentState.rglSlider[k] = newState.rglSlider[k]; - // - server->postEvent(event); - } - } - - ////////// - // POVs // - ////////// - for (k = 0; k < _POVs.size(); ++k) - { - CPOV &pov = _POVs[k]; - if (newState.rgdwPOV[k] != _CurrentState.rgdwPOV[k]) // state changed ? - { - DWORD value = newState.rgdwPOV[k]; - - pov.Centered = (LOWORD(value) == 0xFFFF); - if (!pov.Centered) - { - // update position - pov.Angle = value / 100.f; - } - // create event - CGDPOVChanged *event = new CGDPOVChanged(pov.Centered, pov.Angle, k, this, _EventEmitter); - // update state - _CurrentState.rgdwPOV[k] = newState.rgdwPOV[k]; - // - server->postEvent(event); - } - } - -} - -//============================================================================ -void CDIGameDevice::poll(CInputDeviceServer *dev) -{ - // buffered datas not supported -} - -//============================================================================ -void CDIGameDevice::submit(IInputDeviceEvent *deviceEvent, CEventServer *server) -{ - // should never be called, buffered datas not supported - nlassert(0); -} - - -//============================================================================ -/** Tool fct : tests whether a DIDEVICEOBJECTINSTANCE contains a controls name and return it, - * or build a default one - */ -static void BuildCtrlName(LPCDIDEVICEOBJECTINSTANCE lpddoi, - std::string &destName, - const char *defaultName) -{ - if (lpddoi->dwSize >= offsetof(DIDEVICEOBJECTINSTANCE, tszName) + sizeof(TCHAR[MAX_PATH])) - { - destName = (::strcmp("N/A", lpddoi->tszName) == 0) ? defaultName - : lpddoi->tszName; - } - else - { - destName = defaultName; - } -} - -//============================================================================ -// A callback to enumerate the controls of a device -BOOL CALLBACK DIEnumDeviceObjectsCallback -( - LPCDIDEVICEOBJECTINSTANCE lpddoi, - LPVOID pvRef -) -{ - - CDIGameDevice *gd = (CDIGameDevice *) pvRef; - return gd->processEnumObject(lpddoi); -} - - - -//======================================================================= -// get range for an axis -static HRESULT GetDIAxisRange(LPDIRECTINPUTDEVICE8 device, uint offset, DWORD type, sint &min, sint &max) -{ - DIPROPRANGE diprg; - diprg.diph.dwSize = sizeof(DIPROPRANGE); - diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); - diprg.diph.dwHow = DIPH_BYOFFSET; - diprg.diph.dwObj = offset; - - // Set the range for the axis - HRESULT r = device->GetProperty(DIPROP_RANGE, &diprg.diph); - - if (r == DIERR_OBJECTNOTFOUND) - { - // try from its ID - diprg.diph.dwHow = DIPH_BYID; - diprg.diph.dwObj = type; - - // Set the range for the axis - HRESULT r = device->GetProperty(DIPROP_RANGE, &diprg.diph); - if (r != DI_OK) - { - // setup default values ... - min = 0; - max = 65535; - return r; - } - } - else if (r != DI_OK) - { - min = 0; - max = 65535; - return r; - } - - -/* switch (r) - { - default: - nlinfo("ok"); - break; - case DIERR_INVALIDPARAM: - nlinfo("invalid param"); - break; - case DIERR_NOTEXCLUSIVEACQUIRED: - nlinfo("DIERR_NOTEXCLUSIVEACQUIRED"); - break; - case DIERR_NOTINITIALIZED: - nlinfo("DIERR_NOTINITIALIZED"); - break; - case DIERR_OBJECTNOTFOUND: - nlinfo("DIERR_OBJECTNOTFOUND"); - break; - case DIERR_UNSUPPORTED: - nlinfo("DIERR_UNSUPPORTED"); - break; - }*/ - - - min = (sint) diprg.lMin; - max = (sint) diprg.lMax; - - return r; -} - -//============================================================================ -BOOL CDIGameDevice::processEnumObject(LPCDIDEVICEOBJECTINSTANCE lpddoi) -{ - // the dwSize field gives us the size of the objects, and the available fields - // has this object the field guidType and dwOfs ? - if (lpddoi->dwSize < offsetof(DIDEVICEOBJECTINSTANCE, dwOfs) + sizeof(DWORD)) return DIENUM_CONTINUE; - - uint ctrlType = (uint) lpddoi->dwType; - - /////////////////////////////////////////// - // axis, we only support absolute ones // - /////////////////////////////////////////// - - if (lpddoi->guidType == GUID_XAxis && (ctrlType & DIDFT_ABSAXIS) ) - { - GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Axis[XAxis].Min, _Axis[XAxis].Max); - BuildCtrlName(lpddoi, _Axis[XAxis].Name, "X Axis"); - _Axis[XAxis].Present = true; - return DIENUM_CONTINUE; - } - if (lpddoi->guidType == GUID_YAxis && (ctrlType & DIDFT_ABSAXIS)) - { - GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Axis[YAxis].Min, _Axis[YAxis].Max); - BuildCtrlName(lpddoi, _Axis[YAxis].Name, "Y Axis"); - _Axis[YAxis].Present = true; - return DIENUM_CONTINUE; - } - - if (lpddoi->guidType == GUID_ZAxis && (ctrlType & DIDFT_ABSAXIS)) - { - GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Axis[ZAxis].Min, _Axis[ZAxis].Max); - BuildCtrlName(lpddoi, _Axis[ZAxis].Name, "Z Axis"); - _Axis[ZAxis].Present = true; - return DIENUM_CONTINUE; - } - if (lpddoi->guidType == GUID_RxAxis && (ctrlType & DIDFT_ABSAXIS)) - { - GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Axis[RXAxis].Min, _Axis[RXAxis].Max); - BuildCtrlName(lpddoi, _Axis[RXAxis].Name, "RX Axis"); - _Axis[RXAxis].Present = true; - return DIENUM_CONTINUE; - } - if (lpddoi->guidType == GUID_RyAxis && (ctrlType & DIDFT_ABSAXIS)) - { - GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Axis[RYAxis].Min, _Axis[RYAxis].Max); - BuildCtrlName(lpddoi, _Axis[RYAxis].Name, "RY Axis"); - _Axis[RYAxis].Present = true; - return DIENUM_CONTINUE; - } - if (lpddoi->guidType == GUID_RzAxis && (ctrlType & DIDFT_ABSAXIS)) - { - GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Axis[RZAxis].Min, _Axis[RZAxis].Max); - BuildCtrlName(lpddoi, _Axis[RZAxis].Name, "RZ Axis"); - _Axis[RZAxis].Present = true; - return DIENUM_CONTINUE; - } - - - // has this object the field dwType ? - if (lpddoi->dwSize < offsetof(DIDEVICEOBJECTINSTANCE, dwType) + sizeof(DWORD)) return DIENUM_CONTINUE; - - - uint type = lpddoi->dwType; - ///////////// - // Buttons // - ///////////// - if (type & DIDFT_BUTTON) - { - if (_Buttons.size() < MaxNumButtons) - { - _Buttons.push_back(CButton()); - uint buttonIndex = (uint)_Buttons.size() - 1; - char defaultButtonName[32]; - smprintf(defaultButtonName, 32, "BUTTON %d", buttonIndex + 1); - BuildCtrlName(lpddoi, _Buttons[buttonIndex].Name, defaultButtonName); - return DIENUM_CONTINUE; - } - } - - ///////////// - // Sliders // - ///////////// - if (type & DIDFT_ABSAXIS) - { - if (_Sliders.size() < MaxNumSliders) - { - _Sliders.push_back(CSlider()); - uint sliderIndex = (uint)_Sliders.size() - 1; - GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Sliders[sliderIndex].Min, _Sliders[sliderIndex].Max); - char defaultSliderName[32]; - smprintf(defaultSliderName, 32, "SLIDER %d", sliderIndex + 1); - BuildCtrlName(lpddoi, _Sliders[sliderIndex].Name, defaultSliderName); - } - return DIENUM_CONTINUE; - } - - - ////////// - // POVs // - ////////// - if (type & DIDFT_POV) - { - if (_POVs.size() < MaxNumPOVs) - { - _POVs.push_back(CPOV()); - uint povIndex = (uint)_POVs.size() - 1; - char defaultPOVName[16]; - smprintf(defaultPOVName, 16, "POV %d", povIndex + 1); - BuildCtrlName(lpddoi, _POVs[povIndex].Name, defaultPOVName); - } - return DIENUM_CONTINUE; - } - - return DIENUM_CONTINUE; -} - -//============================================================================ -void CDIGameDevice::querryControls() -{ - HRESULT r = _Device->EnumObjects(&DIEnumDeviceObjectsCallback, (LPVOID) this, DIDFT_ALL); - nlassert(r == DI_OK); -} - -//============================================================================ -bool CDIGameDevice::setBufferSize(uint size) -{ - // uisually not supported by this kind of devices - return false; -} - -//============================================================================ -uint CDIGameDevice::getBufferSize() const -{ - // uisually not supported by this kind of devices - return 0; -} - -//============================================================================ -uint CDIGameDevice::getNumButtons() const -{ - return (uint)_Buttons.size(); -} - -//============================================================================ -bool CDIGameDevice::hasAxis(TAxis axis) const -{ - nlassert(axis < MaxNumAxis); - return _Axis[axis].Present; -} - -//============================================================================ -uint CDIGameDevice::getNumSliders() const -{ - return (uint)_Sliders.size(); -} - -//============================================================================ -uint CDIGameDevice::getNumPOV() const -{ - return (uint)_POVs.size(); -} -//============================================================================ -const char *CDIGameDevice::getButtonName(uint index) const -{ - nlassert(index < _Buttons.size()); - return _Buttons[index].Name.c_str(); -} - -//============================================================================ -const char *CDIGameDevice::getAxisName(TAxis axis) const -{ - nlassert(axis < MaxNumAxis); - nlassert(hasAxis(axis)); // ! Not an axis of this device - return _Axis[axis].Name.c_str(); -} - -//============================================================================ -const char *CDIGameDevice::getSliderName(uint index) const -{ - nlassert(index < _Sliders.size()); - return _Sliders[index].Name.c_str(); -} - -//============================================================================ -const char *CDIGameDevice::getPOVName(uint index) const -{ - nlassert(index < _POVs.size()); - return _POVs[index].Name.c_str(); -} - -//============================================================================ -bool CDIGameDevice::getButtonState(uint index) const -{ - nlassert(index < _Buttons.size()); - return _Buttons[index].Pushed; -} - -//============================================================================ -float CDIGameDevice::getAxisValue(TAxis axis) const -{ - nlassert(axis < MaxNumAxis); - nlassert(hasAxis(axis)); // ! Not an axis of this device - return _Axis[axis].Value; -} - -//============================================================================ -float CDIGameDevice::getSliderPos(uint index) const -{ - nlassert(index < _Sliders.size()); - return _Sliders[index].Pos; -} - -//============================================================================ -float CDIGameDevice::getPOVAngle(uint index) const -{ - nlassert(index < _POVs.size()); - return _POVs[index].Angle; -} - - - -} // NLMISC - - -#endif // NL_OS_WINDOWS diff --git a/code/nel/src/misc/di_game_device.h b/code/nel/src/misc/di_game_device.h deleted file mode 100644 index cc44aaf4c..000000000 --- a/code/nel/src/misc/di_game_device.h +++ /dev/null @@ -1,170 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_DI_GAME_DEVICE_H -#define NL_DI_GAME_DEVICE_H - -#include "nel/misc/types_nl.h" - -#ifdef NL_OS_WINDOWS - -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/game_device.h" - -namespace NLMISC -{ - -// -typedef DIJOYSTATE2 CDIJoyState; -const DIDATAFORMAT * const pJoyDataFormat = &c_dfDIJoystick2; -const uint MaxNumSliders = 2; -const uint MaxNumPOVs = 4; -const uint MaxNumButtons = 128; -// - -struct EDirectInputGameDeviceNotCreated : EDirectInput -{ - EDirectInputGameDeviceNotCreated() : EDirectInput("Unable to create a game device") {} -}; - - -/** - * Direct input implementation of a game device. - */ - -class CDIGameDevice : public IGameDevice -{ -public: - /// Create a direct input game device from the given RGUID. Destroy it with delete - static CDIGameDevice *createGameDevice(IDirectInput8 *di8, - HWND hwnd, - CDIEventEmitter *diEventEmitter, - const CGameDeviceDesc &desc, - REFGUID rguid) throw(EDirectInput); - ~CDIGameDevice(); - - ///\name From IInputDevice - //@{ - virtual bool setBufferSize(uint size); - virtual uint getBufferSize() const; - //@} - - ///\name From IGameDevice - //@{ - virtual const CGameDeviceDesc &getDescription() const { return _Desc; } - // - virtual uint getNumButtons() const; - virtual bool hasAxis(TAxis axis) const; - virtual uint getNumSliders() const; - virtual uint getNumPOV() const; - // - virtual const char *getButtonName(uint index) const; - virtual const char *getAxisName(TAxis axis) const; - virtual const char *getSliderName(uint index) const; - virtual const char *getPOVName(uint index) const; - // - virtual bool getButtonState(uint index) const; - virtual float getAxisValue(TAxis axis) const; - virtual float getSliderPos(uint index) const; - virtual float getPOVAngle(uint index) const; - //@} - - -/////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////// -private: - - // base class for controls - struct CCtrl - { - std::string Name; - }; - - // a button - struct CButton : public CCtrl - { - bool Pushed; - CButton() : Pushed(false) {} - }; - - // an axis. Its value either gives its position (-1 .. 1) or its angle (CCW in radians) - struct CAxis : public CCtrl - { - bool Present; // is this axis used ? - // min and max values from Direct Input - sint Min, Max; - float Value; - CAxis() : Value(0.f), Present(false) {} - }; - - // a slider - struct CSlider : public CCtrl - { - sint Min, Max; - float Pos; - CSlider() : Pos(0.f) {} - }; - - // a POV - struct CPOV : public CCtrl - { - bool Centered; - float Angle; - CPOV() : Angle(0.f), Centered(true) {} - }; - - -private: - // ctor - CDIGameDevice(); - ///\name From IInputDevice - //@{ - virtual void begin(CEventServer *server); - virtual void poll(CInputDeviceServer *dev); - virtual void submit(IInputDeviceEvent *deviceEvent, CEventServer *server); - //@} - /** Get the controls (buttons, slider..) of this device from the Direct Input interface to build this object infos. - */ - void querryControls(); - - /// Called during EnumObject - BOOL processEnumObject(LPCDIDEVICEOBJECTINSTANCE lpddoi); - friend BOOL CALLBACK DIEnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef); -private: - LPDIRECTINPUTDEVICE8 _Device; - CGameDeviceDesc _Desc; - CDIEventEmitter *_EventEmitter; - - ///\name Device infos - //@{ - CAxis _Axis[MaxNumAxis]; - std::vector _Buttons; - std::vector _Sliders; - std::vector _POVs; - //@} - CDIJoyState _CurrentState; - -}; - - -} // NLMISC - -#endif // NL_OS_WINDOWS - - -#endif // NL_DI_GAME_DEVICE_H - -/* End of di_play_device.h */ diff --git a/code/nel/src/misc/di_keyboard_device.cpp b/code/nel/src/misc/di_keyboard_device.cpp deleted file mode 100644 index 8b5d9c6e1..000000000 --- a/code/nel/src/misc/di_keyboard_device.cpp +++ /dev/null @@ -1,686 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - -#include "stdmisc.h" -#include "di_keyboard_device.h" - -#ifdef NL_OS_WINDOWS - -#include "nel/misc/win_event_emitter.h" -#include -#include - -#include "Mmsystem.h" - -#ifdef DEBUG_NEW - #define new DEBUG_NEW -#endif - -namespace NLMISC -{ - -// used to do a conversion from DX key code to Nel keys enums -struct CKeyConv -{ - uint DIKey; - TKey NelKey; - const char *KeyName; - bool Repeatable; -}; - -// this is used to build a conversion table -static const CKeyConv DIToNel[] = -{ - // - {DIK_F1, KeyF1, "F1", true}, - {DIK_F2, KeyF2, "F2", true}, - {DIK_F3, KeyF3, "F3", true}, - {DIK_F4, KeyF4, "F4", true}, - {DIK_F5, KeyF5, "F5", true}, - {DIK_F6, KeyF6, "F6", true}, - {DIK_F7, KeyF7, "F7", true}, - {DIK_F8, KeyF8, "F8", true}, - {DIK_F9, KeyF9, "F9", true}, - {DIK_F10, KeyF10, "F10", true}, - {DIK_F11, KeyF11, "F11", true}, - {DIK_F12, KeyF12, "F12", true}, - {DIK_F13, KeyF13, "F13", true}, - {DIK_F14, KeyF14, "F14", true}, - {DIK_F15, KeyF15, "F15", true}, - // - {DIK_NUMPAD0, KeyNUMPAD0, "NUMPAD0", true}, - {DIK_NUMPAD1, KeyNUMPAD1, "NUMPAD1", true}, - {DIK_NUMPAD2, KeyNUMPAD2, "NUMPAD2", true}, - {DIK_NUMPAD3, KeyNUMPAD3, "NUMPAD3", true}, - {DIK_NUMPAD4, KeyNUMPAD4, "NUMPAD4", true}, - {DIK_NUMPAD5, KeyNUMPAD5, "NUMPAD5", true}, - {DIK_NUMPAD6, KeyNUMPAD6, "NUMPAD6", true}, - {DIK_NUMPAD7, KeyNUMPAD7, "NUMPAD7", true}, - {DIK_NUMPAD8, KeyNUMPAD8, "NUMPAD8", true}, - {DIK_NUMPAD9, KeyNUMPAD9, "NUMPAD9", true}, - // - {DIK_DIVIDE, KeyDIVIDE, "/", true}, - {DIK_DECIMAL, KeyDECIMAL, "NUMPAD .", true}, - // - {DIK_LSHIFT, KeyLSHIFT, "LEFT SHIFT", false}, - {DIK_RSHIFT, KeyRSHIFT, "RIGHT SHIFT", false}, - // - {DIK_LCONTROL, KeyLCONTROL, "LEFT CONTROL", false}, - {DIK_RCONTROL, KeyRCONTROL, "RIGHT CONTROL", false}, - // - {DIK_LMENU, KeyLMENU, "ALT", false}, - {DIK_RMENU, KeyRMENU, "ALT GR", false}, - // - {DIK_UP, KeyUP, "UP", true}, - {DIK_PRIOR, KeyPRIOR, "PRIOR", true}, - {DIK_LEFT, KeyLEFT, "LEFT", true}, - {DIK_RIGHT, KeyRIGHT, "RIGHT", true}, - {DIK_END, KeyEND, "END", true}, - {DIK_DOWN, KeyDOWN, "DOWN", true}, - {DIK_NEXT, KeyNEXT, "NEXT", true}, - {DIK_INSERT, KeyINSERT, "INSERT", true}, - {DIK_DELETE, KeyDELETE, "DELETE", true}, - {DIK_HOME, KeyHOME, "HOME", true}, - {DIK_LWIN, KeyLWIN, "LEFT WIN", false}, - {DIK_RWIN, KeyRWIN, "RIGHT WIN", false}, - {DIK_APPS, KeyAPPS, "APPS", false}, - {DIK_BACK, KeyBACK, "BACK", true}, - // - {DIK_SYSRQ, KeySNAPSHOT, "SNAPSHOT", false}, - {DIK_SCROLL, KeySCROLL, "SCROLL", false}, - {DIK_PAUSE, KeyPAUSE, "PAUSE", false}, - // - {DIK_NUMLOCK, KeyNUMLOCK, "NUMLOCK", false}, - // - {DIK_NUMPADENTER, KeyRETURN, "RETURN", true}, - //{DIK_NUMPADENTER, KeyRETURN, "ENTER", true}, - // - {DIK_CONVERT, KeyCONVERT, "CONVERT", false}, - {DIK_NOCONVERT, KeyNONCONVERT, "NOCONVERT", true}, - // - {DIK_KANA, KeyKANA, "KANA", false}, - {DIK_KANJI, KeyKANJI, "KANJI", false}, -}; - - -///======================================================================== -const CKeyConv *CDIKeyboard::DIKeyToNelKeyTab[CDIKeyboard::NumKeys]; - -///======================================================================== -CDIKeyboard::CDIKeyboard(CWinEventEmitter *we, HWND hwnd) -: _Keyboard(NULL), - _WE(we), - ShiftPressed(false), - CtrlPressed(false), - AltPressed(false), - _CapsLockToggle(true), - _hWnd(hwnd), - _RepeatDelay(250), - _RepeatPeriod(200), - _FirstPressDate(-1), - _LastDIKeyPressed(0) -{ - if (::GetKeyboardState((PBYTE) _VKKeyState) == FALSE) - { - std::fill(_VKKeyState, _VKKeyState + NumKeys, 0); - } - // test whether the user toggle its keyboard with shift or not.. - HKEY hKey; - if (::RegOpenKeyEx(HKEY_CURRENT_USER, "Keyboard Layout", 0, KEY_READ, &hKey) == ERROR_SUCCESS) - { - DWORD type = REG_DWORD; - DWORD value; - DWORD size = sizeof(DWORD); - if (::RegQueryValueEx(hKey, "Attributes", NULL, &type, (LPBYTE) &value, &size) == ERROR_SUCCESS) - { - _CapsLockToggle = (value & (1 << 16)) == 0; - } - ::RegCloseKey(hKey); - } - // get repeat delay and period - int keybDelay; - if (::SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &keybDelay, 0) != 0) - { - _RepeatDelay = 250 + 250 * keybDelay; - } - DWORD keybSpeed; - if (::SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &keybSpeed, 0) != 0) - { - _RepeatPeriod = (uint) (1000.f / (keybSpeed * (27.5f / 31.f) + 2.5f)); - } - // get keyboard layout - _KBLayout = ::GetKeyboardLayout(0); - - _RepetitionDisabled.resize(NumKeys); - _RepetitionDisabled.clearAll(); -} - -///======================================================================== -void CDIKeyboard::updateVKKeyState(uint diKey, bool pressed, TKey &keyValue, TKey &charValue) -{ - bool extKey; - bool repeatable; - keyValue = DIKeyToNelKey(diKey, extKey, repeatable); - // - if (keyValue == 0) - { - charValue = keyValue; - return; - } - // - if (pressed) - { - // check for toggle key - switch (keyValue) - { - case KeyPAUSE: - case KeyKANA: - case KeyKANJI: - _VKKeyState[keyValue] ^= 0x01; // toggle first bit - break; - case KeyCAPITAL: - if (_CapsLockToggle) - { - _VKKeyState[keyValue] ^= 0x01; - //toggleCapsLock(false); - } - else - { - if ((_VKKeyState[keyValue] & 0x01) == 0) - { - _VKKeyState[keyValue] |= 0x01; - //toggleCapsLock(false); - } - } - break; - case KeyNUMLOCK: - _VKKeyState[keyValue] ^= 0x01; - //setNumLock((_VKKeyState[keyValue] & 0x01) != 0); - break; - case KeySCROLL: - _VKKeyState[keyValue] ^= 0x01; - //toggleScrollLock(); - break; - - } - - _VKKeyState[keyValue] |= 0x80; - } - else - { - _VKKeyState[keyValue] &= ~0x80; - } - // - switch (keyValue) - { - case KeyLSHIFT: charValue = KeySHIFT; break; - case KeyRSHIFT: charValue = KeySHIFT; break; - case KeyLCONTROL: charValue = KeyCONTROL; break; - case KeyRCONTROL: charValue = KeyCONTROL; break; - case KeyLMENU: charValue = KeyMENU; break; - case KeyRMENU: charValue = KeyMENU; break; - default: charValue = keyValue; break; - } - // - if (charValue == KeySHIFT && !_CapsLockToggle) - { - if (_VKKeyState[KeyCAPITAL] & 0x01) - { - _VKKeyState[KeyCAPITAL] &= ~0x01; - //toggleCapsLock(true); - } - } - // - if (charValue != keyValue) - { - _VKKeyState[charValue] = _VKKeyState[keyValue]; - } - // - updateCtrlAltShiftValues(); -} - -///======================================================================== -void CDIKeyboard::updateCtrlAltShiftValues() -{ - ShiftPressed = (_VKKeyState[KeySHIFT] & 0x80) != 0; - CtrlPressed = (_VKKeyState[KeyCONTROL] & 0x80) != 0; - AltPressed = (_VKKeyState[KeyMENU] & 0x80) != 0; -} - -///======================================================================== -CDIKeyboard::~CDIKeyboard() -{ - if (_Keyboard) - { - _Keyboard->Unacquire(); - _Keyboard->Release(); - } -} - -///======================================================================== -CDIKeyboard *CDIKeyboard::createKeyboardDevice(IDirectInput8 *di8, - HWND hwnd, - CDIEventEmitter *diEventEmitter, - CWinEventEmitter *we - ) throw(EDirectInput) -{ - std::auto_ptr kb(new CDIKeyboard(we, hwnd)); - kb->_DIEventEmitter = diEventEmitter; - HRESULT result = di8->CreateDevice(GUID_SysKeyboard, &kb->_Keyboard, NULL); - if (result != DI_OK) throw EDirectInputNoKeyboard(); - result = kb->_Keyboard->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); - if (result != DI_OK) throw EDirectInputCooperativeLevelFailed(); - result = kb->_Keyboard->SetDataFormat(&c_dfDIKeyboard); - kb->setBufferSize(16); - kb->_Keyboard->Acquire(); - - // Enable win32 keyboard messages only if hardware mouse in normal mode - if (kb->_WE) - kb->_WE->enableKeyboardEvents(false); - - return kb.release(); -} - -///======================================================================== -void CDIKeyboard::poll(CInputDeviceServer *dev) -{ - nlassert(_Keyboard); - nlassert(_KeyboardBufferSize > 0); - static std::vector datas; - datas.resize(_KeyboardBufferSize); - DWORD numElements = _KeyboardBufferSize; - HRESULT result = _Keyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &datas[0], &numElements, 0); - if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST) - { - result = _Keyboard->Acquire(); - if (result != DI_OK) return; - // get device state - ::GetKeyboardState((unsigned char *) _VKKeyState); - _LastDIKeyPressed = 0; - updateCtrlAltShiftValues(); - result = _Keyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &datas[0], &numElements, 0); - if (result != DI_OK) return; - } - else if (result != DI_OK) - { - return; - } - - _PollTime = (uint32) CTime::getLocalTime(); - - - // process each message in the list - for (uint k = 0; k < numElements; ++k) - { - CDIEvent *die = new CDIEvent; - die->Emitter = this; - die->Datas = datas[k]; - dev->submitEvent(die); - } -} - -///======================================================================== -void CDIKeyboard::transitionOccured(CEventServer *server, const IInputDeviceEvent *nextMessage) -{ - repeatKey(buildDateFromEvent(nextMessage), server); -} - -///======================================================================== -TKeyButton CDIKeyboard::buildKeyButtonsFlags() const -{ - return (TKeyButton) ( (ShiftPressed ? shiftKeyButton : 0) - | (CtrlPressed ? ctrlKeyButton : 0) - | (AltPressed ? altKeyButton : 0) - ); -} - -///======================================================================== -void CDIKeyboard::keyTriggered(bool pressed, uint dikey, CEventServer *server, uint32 date) -{ - #if 0 - const uint numPairs = sizeof(DIToNel) / sizeof(CKeyConv); - for (uint k = 0; k < numPairs; ++k) - { - if (DIToNel[k].DIKey == key) - { - nlinfo(DIToNel[k].KeyName); - } - } - #endif - - - TKey keyValue, charValue; - updateVKKeyState(dikey, pressed, keyValue, charValue); - if (keyValue == 0) return; - - CEventKey *ek; - if (pressed ) - { - ek = new CEventKeyDown(keyValue, buildKeyButtonsFlags(), true, _DIEventEmitter); - } - else - { - ek = new CEventKeyUp(keyValue, buildKeyButtonsFlags(), _DIEventEmitter); - } - server->postEvent(ek); - - if (pressed) - { - if (_RepetitionDisabled[(uint) keyValue] == false) - { - _LastEmitDate = _FirstPressDate = date; - _LastDIKeyPressed = dikey; - } - else // not a repeatable key - { - _LastDIKeyPressed = 0; - return; - } - } - else - { - // key released ? - if (dikey == _LastDIKeyPressed) - { - _LastDIKeyPressed = 0; - } - - if (_RepetitionDisabled[(uint) keyValue] == true) - { - return; - } - } - - // first char event (if repetition not disabled) - if (keyValue >= KeyNUMPAD0 && keyValue <= KeyNUMPAD9 || keyValue == KeyDECIMAL) - { - if ((_VKKeyState[KeyNUMLOCK] & 0x01) != 0) - { - sendUnicode(charValue, dikey, server, pressed); - } - } - else - { - sendUnicode(charValue, dikey, server, pressed); - } - - _FirstPressDate = (uint32) NLMISC::CTime::getLocalTime(); // can't use the time stamp, because we can't not sure it matches the local time. - // time stamp is used for evenrts sorting only -} - -///======================================================================== -void CDIKeyboard::submit(IInputDeviceEvent *deviceEvent, CEventServer *server) -{ - CDIEvent *die = safe_cast(deviceEvent); - bool pressed = (die->Datas.dwData & 0x80) != 0; - keyTriggered(pressed, (uint) die->Datas.dwOfs, server, die->Datas.dwTimeStamp); -} - -///======================================================================== -TMouseButton CDIKeyboard::buildKeyboardButtonFlags() const -{ - nlassert(_Keyboard); - return _DIEventEmitter->buildKeyboardButtonFlags(); -} - -///======================================================================== -bool CDIKeyboard::setBufferSize(uint size) -{ - nlassert(size > 0); - nlassert(_Keyboard); - _Keyboard->Unacquire(); - DIPROPDWORD dipdw; - dipdw.diph.dwSize = sizeof(DIPROPDWORD); - dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); - dipdw.diph.dwObj = 0; - dipdw.diph.dwHow = DIPH_DEVICE; - dipdw.dwData = size; - HRESULT r = _Keyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ); - if (r != DI_OK) return false; - _KeyboardBufferSize = size; - return true; -} - -///======================================================================== -uint CDIKeyboard::getBufferSize() const -{ - return _KeyboardBufferSize; -} - -///======================================================================== -TKey CDIKeyboard::DIKeyToNelKey(uint diKey, bool &extKey, bool &repeatable) -{ - // some key are not handled by MapVirtualKeyEx so we need to convert them ourselves - static bool tableBuilt = false; - - if (!tableBuilt) - { - uint k; - for (k = 0; k < NumKeys; ++k) - { - DIKeyToNelKeyTab[k] = NULL; // set as not a valid key by default - } - const uint numPairs = sizeof(DIToNel) / sizeof(CKeyConv); - for (k = 0; k < numPairs; ++k) - { - DIKeyToNelKeyTab[DIToNel[k].DIKey] = &DIToNel[k]; - } - tableBuilt = true; - } - - - // - if (DIKeyToNelKeyTab[diKey] != NULL) - { - const CKeyConv &keyConv = *DIKeyToNelKeyTab[diKey]; - extKey = true; - repeatable = keyConv.Repeatable; - return keyConv.NelKey; - } - - - - // try doing the conversion using MapVirtualKey - TKey key = (TKey) ::MapVirtualKeyEx(diKey, 1, _KBLayout); - extKey = false; - return key; -} - -///======================================================================== -void CDIKeyboard::sendUnicode(TKey vkey, uint dikey, CEventServer *server, bool pressed) -{ - uint8 oldShift = _VKKeyState[KeySHIFT]; - /// If caps lock is off when pressing shift, we must disable shift, to get no minuscule letters when it is pressed and capslocks is on. - if (!_CapsLockToggle && _VKKeyState[KeyCAPITAL] & 0x01) - { - _VKKeyState[KeySHIFT] = 0; - } - // 'ToUnicode??' is supported since NT4.0 only - // Check if there's support - - - static bool init = false; - static bool toUnicodeSupported = false; - if (!init) - { - init = true; - OSVERSIONINFO osvi; - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (::GetVersionEx (&osvi)) - { - if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) - { - if (osvi.dwMajorVersion >= 4) - { - toUnicodeSupported = true; - } - } - } - } - - - if (toUnicodeSupported) - { - const uint maxNumKeys = 8; - WCHAR keyUnicodes[maxNumKeys]; - int res = ::ToUnicodeEx(vkey, dikey | (pressed ? 0 : (1 << 15)), (unsigned char *) _VKKeyState, keyUnicodes, maxNumKeys, 0, _KBLayout); - // - _VKKeyState[KeySHIFT] = oldShift; - // - for (sint k = 0; k < res; ++k) - { - CEventChar *evc = new CEventChar((ucchar) keyUnicodes[k], buildKeyButtonsFlags(), _DIEventEmitter); - server->postEvent(evc); - } - } - else - { - unsigned char buf[2]; - int res = ::ToAsciiEx(vkey, dikey | (pressed ? 0 : (1 << 15)), (unsigned char *) _VKKeyState, (LPWORD) buf, 0, _KBLayout); - for (sint k = 0; k < res; ++k) - { - CEventChar *evc = new CEventChar((ucchar) buf[k], buildKeyButtonsFlags(), _DIEventEmitter); - server->postEvent(evc); - } - } -} - -///======================================================================== -void CDIKeyboard::repeatKey(uint32 currentDate, CEventServer *server) -{ - if (_LastDIKeyPressed == 0 || _LastDIKeyPressed == DIK_INSERT) return; - bool extKey; - bool repeatable; - TKey vkey = DIKeyToNelKey(_LastDIKeyPressed, extKey, repeatable); - if (vkey == 0) return; - if (currentDate - _FirstPressDate < _RepeatDelay) return; - - sint32 firstDate = _LastEmitDate - (_FirstPressDate + _RepeatDelay); - sint32 lastDate = currentDate - (_FirstPressDate + _RepeatDelay); - if (firstDate < 0) firstDate = 0; - - if (lastDate < firstDate) return; - - uint numRep = (uint) ((lastDate + _RepeatPeriod - 1) / _RepeatPeriod - (firstDate + _RepeatPeriod - 1) / _RepeatPeriod); - //numRep = std::min(16u, numRep); // too much repetitions don't make sense... - if ((sint) numRep < 0) return; // 50 days loop.. - numRep = 1; // fix : for now it seems better to limit the number of repetition to 1 per frame (it can be greater than 1 only if framerate is slow, but its not very useable) - - - // numpad case - if (vkey >= KeyNUMPAD0 && vkey <= KeyNUMPAD9 || vkey == KeyDECIMAL) - { - // check whether numlock is activated - if ((_VKKeyState[KeyNUMLOCK] & 0x01) != 0) - { - for (uint k = 0; k < numRep; ++k) - { - sendUnicode(vkey, _LastDIKeyPressed, server, true); - } - } - else - { - // arrow, home, end.. events - for (uint k = 0; k < numRep; ++k) - { - CEventKey *ek = new CEventKeyDown(vkey, buildKeyButtonsFlags(), false, _DIEventEmitter); - server->postEvent(ek); - } - } - } - else - { - for (uint k = 0; k < numRep; ++k) - { - // if it is an extended key, repetition won't be managed by sendUnicode - if (extKey && repeatable) - { - CEventKey *ek = new CEventKeyDown(vkey, buildKeyButtonsFlags(), false, _DIEventEmitter); - server->postEvent(ek); - } - else - { - sendUnicode(vkey, _LastDIKeyPressed, server, true); - } - } - } - - _LastEmitDate = currentDate; -} - -///======================================================================== -uint32 CDIKeyboard::buildDateFromEvent(const IInputDeviceEvent *deviceEvent) -{ - if (deviceEvent) - { - const CDIEvent *die = safe_cast(deviceEvent); - return (uint32) die->Datas.dwData; - } - else - { - return _PollTime; - } -} - -///======================================================================== -void CDIKeyboard::disableRepetition(const TKey *keyTab, uint numKey) -{ - _RepetitionDisabled.clearAll(); - for (uint k = 0; k < numKey; ++k) - { - _RepetitionDisabled.set((sint) keyTab[k]); - } - - if (_LastDIKeyPressed != 0) - { - bool extKey; - bool repeatable; - TKey key = DIKeyToNelKey(_LastDIKeyPressed, extKey, repeatable); - if (_RepetitionDisabled[(uint) key]) - { - // disable this key repetition - _LastDIKeyPressed = 0; - } - } -} - -///======================================================================== -uint CDIKeyboard::getNumDisabledRepetition() const -{ - uint numKey = 0; - for (uint k = 0; k < NumKeys; ++k) - { - if (_RepetitionDisabled[k]) ++numKey; - } - return numKey; -} - -///======================================================================== -void CDIKeyboard::getDisabledRepetitions(TKey *destTab) const -{ - for (uint k = 0; k < NumKeys; ++k) - { - if (_RepetitionDisabled[k]) *destTab++ = (TKey) k; - } -} - - - -} // NLMISC - -#endif // NL_OS_WINDOWS diff --git a/code/nel/src/misc/di_keyboard_device.h b/code/nel/src/misc/di_keyboard_device.h deleted file mode 100644 index d28285894..000000000 --- a/code/nel/src/misc/di_keyboard_device.h +++ /dev/null @@ -1,163 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_DI_KEYBOARD_H -#define NL_DI_KEYBOARD_H - -#include "nel/misc/types_nl.h" - -#ifdef NL_OS_WINDOWS - -#include "nel/misc/input_device_server.h" -#include "nel/misc/keyboard_device.h" -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/bit_set.h" - - - - - -namespace NLMISC -{ - -class CWinEventEmitter; - -// -struct EDirectInputNoKeyboard : public EDirectInput -{ - EDirectInputNoKeyboard() : EDirectInput("No keyboard found") {} -}; - - -struct CKeyConv; - -/** - * Direct Input implementation of a keyboard. - * \see CDIEventEmitter - * \author Nicolas Vizerie - * \author Nevrax France - * \date 2002 - */ -class CDIKeyboard : public IKeyboardDevice -{ -public: - bool ShiftPressed, CtrlPressed, AltPressed; -public: - ///\name Object - //@{ - /** Create a keyboard device, that must then be deleted by the caller - * An optional WinEventEmiter can be provided, so that its flags can be in sync - * with a win32 keyboard flags (shift, ctrl, and alt) - */ - static CDIKeyboard *createKeyboardDevice(IDirectInput8 *di8, - HWND hwnd, - CDIEventEmitter *diEventEmitter, - CWinEventEmitter *we = NULL - ) throw(EDirectInput); - // dtor - virtual ~CDIKeyboard(); - //@} - - ///\name From IInputDevice - //@{ - virtual bool setBufferSize(uint size); - virtual uint getBufferSize() const; - //@} - - ///\name From IInputDevice - //@{ - uint getKeyRepeatDelay() const { return _RepeatDelay; } - void setKeyRepeatDelay(uint delay) { nlassert(delay > 0); _RepeatDelay = delay; } - uint getKeyRepeatPeriod() const { return _RepeatPeriod; } - void setKeyRepeatPeriod(uint period) { nlassert(period > 0); _RepeatPeriod = period; } - void disableRepetition(const TKey *keyTab, uint numKey); - uint getNumDisabledRepetition() const; - void getDisabledRepetitions(TKey *destTab) const; - //@} - - TMouseButton buildKeyboardFlags() const; -/////////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////// -private: - // - bool _CapsLockToggle; // true if caps lock off is triggered by caps lock, false if it toggled by shift - uint _RepeatDelay; // the delay before a key is repeated (in ms) - uint _RepeatPeriod; // The period for key repetitions (in ms) - // - LPDIRECTINPUTDEVICE8 _Keyboard; - uint _KeyboardBufferSize; - // virtual code state - uint8 _VKKeyState[NumKeys]; - // tells for which keys repetition is disabled - CBitSet _RepetitionDisabled; - // The date at which the last key pressed has been pressed (not using 64 bits since note handled by Direct Input) - uint32 _FirstPressDate; - // The last date at which key repetition occured (not using 64 bits since note handled by Direct Input) - uint32 _LastEmitDate; - // The system date at which the last polling occured (not using 64 bits since note handled by Direct Input) - uint32 _PollTime; - uint _LastDIKeyPressed; - CWinEventEmitter *_WE; - HWND _hWnd; - HKL _KBLayout; - // - CDIEventEmitter *_DIEventEmitter; - // - static const CKeyConv *DIKeyToNelKeyTab[NumKeys]; -private: - /// ctor - CDIKeyboard(CWinEventEmitter *we, HWND hwnd); - /** Convert a direct input scancode to a virtual key. Note that DirectInput scancodes do not always match system scan codes. - * Repeatable has a meaning only for extended keys - */ - TKey DIKeyToNelKey(uint diKey, bool &extKey, bool &repeatable); - /** This update virtual key state table. - * \param keyValue contains the value to send to a EventKeyDown or EventKeyUp message. - * \param charValue contains the value that must be used for Unicode conversion (which generate EventChar messages) - */ - void updateVKKeyState(uint diKey, bool pressed, TKey &keyValue, TKey &charValue); - // Use the given virtual key code and the current keyb state to produce Unicode - void sendUnicode(TKey vkey, uint dikey, CEventServer *server, bool pressed); - // Build a TKeyButton value from the state of shift, ctrl and alt - TKeyButton buildKeyButtonsFlags() const; - // Update the state of this object and send the appropriate message when a direct / input key has been pressed / released - void keyTriggered(bool pressed, uint key, CEventServer *server, uint32 date); - // The same as buildKeyButtonsFlags(), but the return is a TMouseButtonValue (with no mouse value setupped) - TMouseButton buildKeyboardButtonFlags() const; - // setup the state of the Ctrl, Alt and Shift key from the state in the _VKKeyState buffer - void updateCtrlAltShiftValues(); - /// Repeat the current key, and create events - void repeatKey(uint32 currentDate, CEventServer *server); - /// Build a date by using an event time stamp, or generate one if NULL - uint32 buildDateFromEvent(const IInputDeviceEvent *deviceEvent); - - ///\name From IInputDevice - //@{ - virtual void poll(CInputDeviceServer *dev); - virtual void submit(IInputDeviceEvent *deviceEvent, CEventServer *server); - virtual void transitionOccured(CEventServer *server, const IInputDeviceEvent *nextMessage); - //@} -}; - - -} // NLMISC - - -#endif // NL_OS_WINDOWS - -#endif // NL_DI_KEYBOARD_H - -/* End of di_keyboard.h */ diff --git a/code/nel/src/misc/di_mouse_device.cpp b/code/nel/src/misc/di_mouse_device.cpp deleted file mode 100644 index 273725c5c..000000000 --- a/code/nel/src/misc/di_mouse_device.cpp +++ /dev/null @@ -1,507 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdmisc.h" - -#include "di_mouse_device.h" -#include "nel/misc/game_device_events.h" -#include "nel/misc/win_event_emitter.h" - - -#ifdef NL_OS_WINDOWS - -#ifdef DEBUG_NEW - #define new DEBUG_NEW -#endif - -#ifdef NL_COMP_MINGW -# undef FIELD_OFFSET -# define FIELD_OFFSET(t,f) offsetof(t,f) -#endif - - -namespace NLMISC -{ - -//====================================================== -CDIMouse::CDIMouse() : _MessageMode(RawMode), - _MouseSpeed(1.0f), - _MouseAccel(10000), - _Mouse(NULL), - _XAcc(0), - _YAcc(0), - _XMousePos(0), - _YMousePos(0), - _LastMouseButtonClicked(-1), - _DoubleClickDelay(300), - _XFactor(1.f), - _YFactor(1.f), - OldDIXPos(0), - OldDIYPos(0), - OldDIZPos(0), - _FirstX(true), - _FirstY(true), - _SwapButton(false) - -{ - std::fill(_MouseButtons, _MouseButtons + MaxNumMouseButtons, false); - std::fill(_MouseAxisMode, _MouseAxisMode + NumMouseAxis, Raw); - _MouseFrame.setWH(0, 0, 640, 480); -} - -//====================================================== -CDIMouse::~CDIMouse() -{ - if (_Mouse) - { - _Mouse->Unacquire(); - _Mouse->Release(); - } -} - -//====================================================== -void CDIMouse::setMouseMode(TAxis axis, TAxisMode axisMode) -{ - nlassert(axisMode < AxisModeLast); - nlassert(axis < AxisLast); - _MouseAxisMode[axis] = axisMode; - clampMouseAxis(); -} - -//====================================================== -CDIMouse::TAxisMode CDIMouse::getMouseMode(TAxis axis) const -{ - nlassert((int)axis < (int)NumMouseAxis); - return _MouseAxisMode[axis]; -} - -//====================================================== -void CDIMouse::setMouseSpeed(float speed) -{ - nlassert(_MessageMode == NormalMode); - nlassert(speed > 0); - _MouseSpeed = speed; -} - -//====================================================== -void CDIMouse::setMouseAcceleration(uint accel) -{ - _MouseAccel = accel; -} - -//====================================================== -uint CDIMouse::getMouseAcceleration() const -{ - return _MouseAccel; -} - -//====================================================== -bool CDIMouse::setBufferSize(uint size) -{ - nlassert(size > 0); - nlassert(_Mouse); - _Mouse->Unacquire(); - DIPROPDWORD dipdw; - dipdw.diph.dwSize = sizeof(DIPROPDWORD); - dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); - dipdw.diph.dwObj = 0; - dipdw.diph.dwHow = DIPH_DEVICE; - dipdw.dwData = size; - HRESULT r = _Mouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ); - if (r != DI_OK) return false; - _MouseBufferSize = size; - return true; -} - -//====================================================== -uint CDIMouse::getBufferSize() const { return _MouseBufferSize; } - -//====================================================== -void CDIMouse::setMousePos(float x, float y) -{ - nlassert(_MessageMode == NormalMode); - _XMousePos = (sint64) ((double) x * ((sint64) 1 << 32)); - _YMousePos = (sint64) ((double) y * ((sint64) 1 << 32)); -} - -//====================================================== -CDIMouse *CDIMouse::createMouseDevice(IDirectInput8 *di8, HWND hwnd, CDIEventEmitter *diEventEmitter, bool hardware, CWinEventEmitter *we) throw(EDirectInput) -{ - std::auto_ptr mouse(new CDIMouse); - mouse->_DIEventEmitter = diEventEmitter; - mouse->_Hardware = hardware; - HRESULT result = di8->CreateDevice(GUID_SysMouse, &(mouse->_Mouse), NULL); - if (result != DI_OK) throw EDirectInputNoMouse(); - result = mouse->_Mouse->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | (!hardware ? DISCL_EXCLUSIVE:DISCL_NONEXCLUSIVE)); - if (result != DI_OK) throw EDirectInputCooperativeLevelFailed(); - mouse->_Mouse->SetDataFormat(&c_dfDIMouse2); - mouse->setBufferSize(64); - mouse->_WE = we; - mouse->setDoubleClickDelay(::GetDoubleClickTime()); - - /** we want an absolute mouse mode, so that, if the event buffer get full, we can retrieve the right position - */ - DIPROPDWORD prop; - prop.diph.dwSize = sizeof(DIPROPDWORD); - prop.diph.dwHeaderSize = sizeof(DIPROPHEADER); - prop.diph.dwHow = DIPH_DEVICE; - prop.diph.dwObj = 0; - prop.dwData = DIPROPAXISMODE_ABS; - HRESULT r = mouse->_Mouse->SetProperty(DIPROP_AXISMODE, &prop.diph); - nlassert(r == DI_OK); // should always succeed... - // - mouse->_Mouse->Acquire(); - mouse->_hWnd = hwnd; - - // Enable win32 mouse message only if hardware mouse in normal mode - if (mouse->_WE) - mouse->_WE->enableMouseEvents(mouse->_Hardware && (mouse->_MessageMode == IMouseDevice::NormalMode)); - - mouse->_SwapButton = GetSystemMetrics(SM_SWAPBUTTON) != 0; - - return mouse.release(); -} - -//====================================================== -float CDIMouse::getMouseSpeed() const -{ - nlassert(_MessageMode == NormalMode); - return _MouseSpeed; -} - -//====================================================== -const CRect &CDIMouse::getMouseFrame() const -{ - nlassert(_MessageMode == NormalMode); - return _MouseFrame; -} - -//====================================================== -uint CDIMouse::getDoubleClickDelay() const { return _DoubleClickDelay; } - -//====================================================== -inline void CDIMouse::clampMouseAxis() -{ - if (_MouseAxisMode[XAxis] == Clamped) clamp(_XMousePos, (sint64) _MouseFrame.X << 32, (sint64) (_MouseFrame.X + _MouseFrame.Width - 1) << 32); - if (_MouseAxisMode[YAxis] == Clamped) clamp(_YMousePos, (sint64) _MouseFrame.Y << 32, (sint64) (_MouseFrame.X + _MouseFrame.Height - 1) << 32); -} - -//====================================================== -void CDIMouse::poll(CInputDeviceServer *dev) -{ - nlassert(_Mouse); - nlassert(_MouseBufferSize > 0); - static std::vector datas; - datas.resize(_MouseBufferSize); - DWORD numElements = _MouseBufferSize; - HRESULT result = _Mouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &datas[0], &numElements, 0); - if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST) - { - result = _Mouse->Acquire(); - HRESULT result = _Mouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &datas[0], &numElements, 0); - if (result != DI_OK) return; - } - else if (result != DI_OK) return; - - if (::IsWindowEnabled(_hWnd) && ::IsWindowVisible(_hWnd)) - { - for(uint k = 0; k < numElements; ++k) - { - CDIEvent *die = new CDIEvent; - die->Emitter = this; - die->Datas = datas[k]; - dev->submitEvent(die); - } - } -} - - -//====================================================================== -TMouseButton CDIMouse::buildMouseButtonFlags() const -{ - if (_SwapButton) - return (TMouseButton) ( - _DIEventEmitter->buildKeyboardButtonFlags() - | (_MouseButtons[0] ? rightButton : 0) - | (_MouseButtons[1] ? leftButton : 0) - | (_MouseButtons[2] ? middleButton : 0) - ); - else - return (TMouseButton) ( - _DIEventEmitter->buildKeyboardButtonFlags() - | (_MouseButtons[0] ? leftButton : 0) - | (_MouseButtons[1] ? rightButton : 0) - | (_MouseButtons[2] ? middleButton : 0) - ); -} - -//====================================================== -TMouseButton CDIMouse::buildMouseSingleButtonFlags(uint button) -{ - static const TMouseButton mb[] = { leftButton, rightButton, middleButton }; - static const TMouseButton mbswap[] = { rightButton, leftButton, middleButton }; - nlassert(button < MaxNumMouseButtons); - if (_SwapButton) - return (TMouseButton) (_DIEventEmitter->buildKeyboardButtonFlags() | mbswap[button]); - else - return (TMouseButton) (_DIEventEmitter->buildKeyboardButtonFlags() | mb[button]); -} - -//====================================================== -void CDIMouse::onButtonClicked(uint button, CEventServer *server, uint32 date) -{ - // check for double click - if (_LastMouseButtonClicked == (sint) button) - { - if (date - _MouseButtonsLastClickDate < _DoubleClickDelay) - { - CEventMouseDblClk *emdc - = new CEventMouseDblClk((float) (_XMousePos >> 32), - (float) (_YMousePos >> 32), - buildMouseSingleButtonFlags(button), - _DIEventEmitter); - server->postEvent(emdc); - _LastMouseButtonClicked = -1; - } - else - { - _MouseButtonsLastClickDate = date; - } - } - else - { - _LastMouseButtonClicked = button; - _MouseButtonsLastClickDate = date; - } -} - -//====================================================== -void CDIMouse::processButton(uint button, bool pressed, CEventServer *server, uint32 date) -{ - updateMove(server); - float mx = (float) (_XFactor * (double) _XMousePos / ((double) 65536 * (double) 65536)); - float my = (float) (_YFactor * (double) _YMousePos / ((double) 65536 * (double) 65536)); - if (pressed) - { - CEventMouseDown *emd = - new CEventMouseDown(mx, my, buildMouseSingleButtonFlags(button), - _DIEventEmitter); - server->postEvent(emd); - } - else - { - CEventMouseUp *emu = - new CEventMouseUp(mx, my, buildMouseSingleButtonFlags(button), _DIEventEmitter); - server->postEvent(emu); - onButtonClicked(button, server, date); - } - _MouseButtons[button] = pressed; -} - -//====================================================== -void CDIMouse::submit(IInputDeviceEvent *deviceEvent, CEventServer *server) -{ - if (!_Hardware || (_MessageMode == RawMode)) - { - CDIEvent *die = safe_cast(deviceEvent); - bool pressed; - switch(die->Datas.dwOfs) - { - case DIMOFS_X: - { - if (!_FirstX) - { - sint dep = (sint32) die->Datas.dwData - OldDIXPos; - - // Acceleration - if (_MouseAccel) - { - sint accelFactor = abs (dep) / (sint)_MouseAccel; - dep <<= accelFactor; - } - - _XAcc += dep; - } - else - { - _FirstX = false; - } - OldDIXPos = (sint32) die->Datas.dwData; - } - break; - case DIMOFS_Y: - { - if (!_FirstY) - { - sint dep = (sint32) die->Datas.dwData - OldDIYPos; - - // Acceleration - if (_MouseAccel) - { - sint accelFactor = abs (dep) / (sint)_MouseAccel; - dep <<= accelFactor; - } - - _YAcc -= dep; - } - else - { - _FirstY = false; - } - OldDIYPos = (sint32) die->Datas.dwData; - } - break; - case DIMOFS_Z: - { - updateMove(server); - sint dep = die->Datas.dwData - OldDIZPos; - OldDIZPos = (sint32) die->Datas.dwData; - CEventMouseWheel *emw = - new CEventMouseWheel((float) (_XMousePos >> 32), - (float) (_XMousePos >> 32), - buildMouseButtonFlags(), - dep > 0, - _DIEventEmitter); - server->postEvent(emw); - } - break; - case DIMOFS_BUTTON0: /* left button */ - pressed = (die->Datas.dwData & 0x80) != 0; - processButton(0, pressed, server, die->Datas.dwTimeStamp); - break; - case DIMOFS_BUTTON1: /* right button */ - pressed = (die->Datas.dwData & 0x80) != 0; - processButton(1, pressed, server, die->Datas.dwTimeStamp); - break; - case DIMOFS_BUTTON2: /* middle button */ - pressed = (die->Datas.dwData & 0x80) != 0; - processButton(2, pressed, server, die->Datas.dwTimeStamp); - break; - default: - return; - break; - } - } -} - -//====================================================== -void CDIMouse::updateMove(CEventServer *server) -{ - if (_XAcc != 0 || _YAcc != 0) - { - if (_MessageMode == NormalMode) - { - _XMousePos += (sint64) ((double) _MouseSpeed * (sint64) _XAcc * ((sint64) 1 << 32)); - _YMousePos += (sint64) ((double) _MouseSpeed * (sint64) _YAcc * ((sint64) 1 << 32)); - clampMouseAxis(); - CEventMouseMove *emm = new CEventMouseMove((float) (_XFactor * (double) _XMousePos / ((double) 65536 * (double) 65536)), (float) (_YFactor * (double) _YMousePos / ((double) 65536 * (double) 65536)), buildMouseButtonFlags(), _DIEventEmitter); - server->postEvent(emm); - } - else - { - CGDMouseMove *emm = new CGDMouseMove(_DIEventEmitter, this, _XAcc, _YAcc); - server->postEvent(emm); - } - _XAcc = _YAcc = 0; - } -} - - -//====================================================== -void CDIMouse::convertStdMouseMoveInMickeys(float &dx, float &dy) const -{ - // get in same scale as _XAcc and _YAcc - double xacc= ((double)dx/_XFactor) / _MouseSpeed; - double yacc= ((double)dy/_YFactor) / _MouseSpeed; - - dx= float(xacc); - dy =float(yacc); -} - - -//====================================================== -void CDIMouse::transitionOccured(CEventServer *server, const IInputDeviceEvent *) -{ - updateMove(server); -} - -//====================================================== -void CDIMouse::setButton(uint button, bool pushed) -{ - nlassert(button < MaxNumMouseButtons); - _MouseButtons[button] = pushed; -} - -//====================================================== -bool CDIMouse::getButton(uint button) const -{ - nlassert(button < MaxNumMouseButtons); - return _MouseButtons[button]; -} - -//====================================================== -void CDIMouse::setDoubleClickDelay(uint ms) -{ - nlassert(ms > 0); - _DoubleClickDelay = ms; -} - -//====================================================== -void CDIMouse::setMouseFrame(const CRect &rect) -{ - nlassert(_MessageMode == NormalMode); - _MouseFrame = rect; -} - -//====================================================== -void CDIMouse::setMessagesMode(TMessageMode mode) -{ - nlassert(mode < MessageModeLast); - _MessageMode = mode; - _FirstX = _FirstY = true; - - // Enable win32 mouse message only if hardware mouse in normal mode - if (_WE) - _WE->enableMouseEvents(_Hardware && (_MessageMode == NormalMode)); -} - - -} // NLMISC - -#endif // NL_OS_WINDOWS - - - - - - - - - - - - - - - - - - - - - - - diff --git a/code/nel/src/misc/di_mouse_device.h b/code/nel/src/misc/di_mouse_device.h deleted file mode 100644 index aab678ffc..000000000 --- a/code/nel/src/misc/di_mouse_device.h +++ /dev/null @@ -1,167 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_DI_MOUSE_DEVICE_H -#define NL_DI_MOUSE_DEVICE_H - -#include "nel/misc/types_nl.h" - -#ifdef NL_OS_WINDOWS - - -#include "nel/misc/rect.h" -#include "nel/misc/di_event_emitter.h" -#include "nel/misc/input_device_server.h" -#include "nel/misc/mouse_device.h" -#include - - -namespace NLMISC -{ - - -// -struct EDirectInputNoMouse : public EDirectInput -{ - EDirectInputNoMouse() : EDirectInput("No mouse found") {} -}; - - -class CDXEventEmitter; - - -/** - * Direct Input implementation of a mouse - * \see CDIEventEmitter - * \author Nicolas Vizerie - * \author Nevrax France - * \date 2002 - */ -class CDIMouse : public IMouseDevice -{ -public: - enum { MaxNumMouseButtons = 3, NumMouseAxis = 3}; -public: - ///\name Object - //@{ - virtual ~CDIMouse(); - /** Create a mouse device from a valid DirectInput8 pointer. This must then be deleted by the caller. - * \return the interface or throw an exception if the creation failed - */ - static CDIMouse *createMouseDevice(IDirectInput8 *di8, HWND hwnd, CDIEventEmitter *diEventEmitter, bool hardware, class CWinEventEmitter *we) throw(EDirectInput); - //@} - - ///\name Mouse params, inherited from IMouseDevice - //@{ - void setMessagesMode(TMessageMode mode); - TMessageMode getMessagesMode() const { return _MessageMode; } - void setMouseMode(TAxis axis, TAxisMode axisMode); - TAxisMode getMouseMode(TAxis axis) const; - void setMouseSpeed(float speed); - float getMouseSpeed() const; - void setMouseAcceleration(uint speed); - uint getMouseAcceleration() const; - void setMouseFrame(const CRect &rect); - const CRect &getMouseFrame() const; - void setDoubleClickDelay(uint ms); - uint getDoubleClickDelay() const; - void setMousePos(float x, float y); - void setFactors(float xFactor, float yFactor) - { - nlassert(_MessageMode == NormalMode); - _XFactor = xFactor; - _YFactor = yFactor; - } - float getXFactor() const { nlassert(_MessageMode == NormalMode); return _XFactor; } - float getYFactor() const { nlassert(_MessageMode == NormalMode); return _YFactor; } - void convertStdMouseMoveInMickeys(float &dx, float &dy) const; - //@} - - ///\name From IInputDevice - //@{ - - virtual bool setBufferSize(uint size); - virtual uint getBufferSize() const; - //@} - - ///\name From IInputDevice - //@{ - void setButton(uint button, bool pushed); - bool getButton(uint button) const; - //@} - -////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////// - -private: - LPDIRECTINPUTDEVICE8 _Mouse; - // - bool _Hardware; - // - TMessageMode _MessageMode; - // - TAxisMode _MouseAxisMode[NumMouseAxis]; - sint64 _XMousePos, _YMousePos; // position encoded in fixed point 32 : 32. This allow wrapping and no loss of precision, when not in clamped mode - // NB: this is sint64 because of max range reached with 16:16 when looping around x with great mouse speed - bool _FirstX, _FirstY; - float _MouseSpeed; - uint _MouseAccel; - CRect _MouseFrame; - // - bool _MouseButtons[MaxNumMouseButtons]; - uint32 _MouseButtonsLastClickDate; - sint _LastMouseButtonClicked; - uint _DoubleClickDelay; - uint _MouseBufferSize; - HWND _hWnd; - // - sint32 OldDIXPos, OldDIYPos, OldDIZPos; // old positions reported by direct input - sint _XAcc, _YAcc; // accumulate move (needed because they are generated on a single axis for each DI event) - float _XFactor, _YFactor; - // - CDIEventEmitter *_DIEventEmitter; - // The windows emitter to enable / disble win32 mouse messages - NLMISC::CRefPtr _WE; - // Does the button left and right are swapped ? - bool _SwapButton; -private: - /// ctor - CDIMouse(); - /// Clamp the mouse axis that need to be. - void clampMouseAxis(); - /// Sum the mouse move and produce an event - void updateMove(CEventServer *server); - void processButton(uint button, bool pressed, CEventServer *server, uint32 date); - TMouseButton buildMouseButtonFlags() const; - TMouseButton buildMouseSingleButtonFlags(uint button); - void onButtonClicked(uint button, CEventServer *server, uint32 date); - ///\name From IInputDevice - //@{ - virtual void poll(CInputDeviceServer *dev); - virtual void submit(IInputDeviceEvent *deviceEvent, CEventServer *server); - virtual void transitionOccured(CEventServer *server, const IInputDeviceEvent *nextMessage); - //@} -}; - - -} // NL3D - - -#endif // NL_OS_WINDOWS - -#endif // NL_DI_MOUSE_H - -/* End of di_mouse.h */ diff --git a/code/nel/src/misc/event_emitter_multi.cpp b/code/nel/src/misc/event_emitter_multi.cpp index 52bc235cd..45559ebc4 100644 --- a/code/nel/src/misc/event_emitter_multi.cpp +++ b/code/nel/src/misc/event_emitter_multi.cpp @@ -84,11 +84,6 @@ void CEventEmitterMulti::submitEvents(CEventServer &server, bool allWindows) } } -///============================================================ -void CEventEmitterMulti::emulateMouseRawMode(bool enable) -{ -} - ///============================================================ IEventEmitter *CEventEmitterMulti::getEmitter(uint index) { diff --git a/code/nel/src/misc/game_device.cpp b/code/nel/src/misc/game_device.cpp deleted file mode 100644 index 2ba49367f..000000000 --- a/code/nel/src/misc/game_device.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdmisc.h" -#include "nel/misc/game_device.h" - -#ifdef DEBUG_NEW - #define new DEBUG_NEW -#endif - -namespace NLMISC { - - - -} // NLMISC diff --git a/code/nel/src/misc/game_device_events.cpp b/code/nel/src/misc/game_device_events.cpp deleted file mode 100644 index bf64a1c4b..000000000 --- a/code/nel/src/misc/game_device_events.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdmisc.h" -#include "nel/misc/game_device_events.h" - - -#ifdef DEBUG_NEW - #define new DEBUG_NEW -#endif - -namespace NLMISC -{ - -void dummyToAvoidStupidCompilerWarning_game_device_events_cpp() -{ - -} - -} // NLMISC diff --git a/code/nel/src/misc/input_device.cpp b/code/nel/src/misc/input_device.cpp deleted file mode 100644 index 3825935a6..000000000 --- a/code/nel/src/misc/input_device.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdmisc.h" -#include "nel/misc/input_device.h" - -// remove stupid VC6 warnings -void foo_input_device_cpp() {} - -#ifdef DEBUG_NEW - #define new DEBUG_NEW -#endif - -namespace NLMISC -{ - - -} // NLMISC diff --git a/code/nel/src/misc/input_device_server.cpp b/code/nel/src/misc/input_device_server.cpp deleted file mode 100644 index 253b68e71..000000000 --- a/code/nel/src/misc/input_device_server.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdmisc.h" - -#include "nel/misc/input_device_server.h" -#include "nel/misc/input_device.h" -#include "nel/misc/debug.h" - -#ifdef DEBUG_NEW - #define new DEBUG_NEW -#endif - -namespace NLMISC -{ -//======================================================================= -void CInputDeviceServer::registerDevice(IInputDevice *device) -{ - nlassert(!isDevice(device)); - _Devices.push_back(device); -} - -//======================================================================= -void CInputDeviceServer::removeDevice(IInputDevice *device) -{ - TDeviceCont::iterator it = std::find(_Devices.begin(), _Devices.end(), device); - nlassert(it != _Devices.end()); - _Devices.erase(it); -} - -//======================================================================= -bool CInputDeviceServer::isDevice(IInputDevice *device) const -{ - TDeviceCont::const_iterator it = std::find(_Devices.begin(), _Devices.end(), device); - return it != _Devices.end(); -} - -//======================================================================= -// Predicate to compare vents dates -struct CInputDeviceEventLess -{ - bool operator()(const IInputDeviceEvent *lhs, const IInputDeviceEvent *rhs) const - { - return *lhs < *rhs; - } -}; - -//======================================================================= -void CInputDeviceServer::poll(CEventServer *server) -{ - nlassert(_Events.empty()); - TDeviceCont::iterator deviceIt; - for (deviceIt = _Devices.begin(); deviceIt != _Devices.end(); ++deviceIt) - { - (*deviceIt)->begin(server); - (*deviceIt)->poll(this); - } - // Sort the messages to get the right dates. - std::sort(_Events.begin(), _Events.end(), CInputDeviceEventLess()); - // submit the result to the server - IInputDevice *lastVisitedDevice = NULL; - TEventCont::iterator eventIt; - for (eventIt = _Events.begin(); eventIt != _Events.end(); ++eventIt) - { - // see if this message is from a previous device then the last we visited. - if (lastVisitedDevice && (*eventIt)->Emitter != lastVisitedDevice) - { - // yes, tells that a transition occured - lastVisitedDevice->transitionOccured(server, *eventIt); - lastVisitedDevice = (*eventIt)->Emitter; - } - nlassert((*eventIt)->Emitter != NULL); - (*eventIt)->Emitter->submit(*eventIt, server); - } - // - for (deviceIt = _Devices.begin(); deviceIt != _Devices.end(); ++deviceIt) - { - (*deviceIt)->transitionOccured(server, NULL); - } - // delete the messages - for (eventIt = _Events.begin(); eventIt != _Events.end(); ++eventIt) - { - delete *eventIt; - } - // - _Events.clear(); -} - -//======================================================================= -void CInputDeviceServer::submitEvent(IInputDeviceEvent *deviceEvent) -{ - _Events.push_back(deviceEvent); -} - - -} // NLMISC diff --git a/code/nel/src/misc/keyboard_device.cpp b/code/nel/src/misc/keyboard_device.cpp deleted file mode 100644 index 4c7f353bc..000000000 --- a/code/nel/src/misc/keyboard_device.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdmisc.h" - -//#include "nel/3d/u_keyboard_device.h" - -#ifdef DEBUG_NEW - #define new DEBUG_NEW -#endif - -namespace NL3D { - - -/* - * Constructor - */ -/*UKeyboardDevice::UKeyboardDevice() -{ -}*/ - - -} // NL3D diff --git a/code/nel/src/misc/win_event_emitter.cpp b/code/nel/src/misc/win_event_emitter.cpp index 3c74d9241..01da89564 100644 --- a/code/nel/src/misc/win_event_emitter.cpp +++ b/code/nel/src/misc/win_event_emitter.cpp @@ -57,14 +57,6 @@ void CWinEventEmitter::submitEvents(CEventServer & server, bool allWindows) _InternalServer.pump (allWindows); } -/*------------------------------------------------------------------*\ - emulateMouseRawMode() -\*------------------------------------------------------------------*/ -void CWinEventEmitter::emulateMouseRawMode(bool enable) -{ - nlerror("no raw mode emulation on windows, the CDIMouse has a real raw mode"); -} - /*------------------------------------------------------------------*\ processMessage() \*------------------------------------------------------------------*/ @@ -320,7 +312,7 @@ bool CWinEventEmitter::processMessage (HWND hWnd, uint32 msg, WPARAM wParam, LPA case WM_INPUTLANGCHANGE: if ( _IMEEventsEnabled ) { - // wParam = Specifies the character set of the new locale. + // wParam = Specifies the character set of the new locale. // lParam = Input locale identifier. server->postEvent( new CEventIME( msg, (uint32)wParam, (uint32)lParam, this ) ); return true; // trap message diff --git a/code/ryzom/client/client_default.cfg b/code/ryzom/client/client_default.cfg index a27e69ee0..2846713fc 100644 --- a/code/ryzom/client/client_default.cfg +++ b/code/ryzom/client/client_default.cfg @@ -214,6 +214,12 @@ Shadows_ps1 = 1; Shadows_ps2 = 1; Shadows_ps3 = 1; +FXAA = 1; +FXAA_ps0 = 0; +FXAA_ps1 = 1; +FXAA_ps2 = 1; +FXAA_ps3 = 1; + Bloom = 0; Bloom_ps0 = 0; Bloom_ps1 = 1; diff --git a/code/ryzom/client/client_default.cfg.in b/code/ryzom/client/client_default.cfg.in index 030a4a2b2..ec699fe14 100644 --- a/code/ryzom/client/client_default.cfg.in +++ b/code/ryzom/client/client_default.cfg.in @@ -210,6 +210,12 @@ Shadows_ps1 = 1; Shadows_ps2 = 1; Shadows_ps3 = 1; +FXAA = 1; +FXAA_ps0 = 0; +FXAA_ps1 = 1; +FXAA_ps2 = 1; +FXAA_ps3 = 1; + Bloom = 0; Bloom_ps0 = 0; Bloom_ps1 = 1; diff --git a/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml b/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml index 5e9072b93..c2b62cebd 100644 --- a/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml +++ b/code/ryzom/client/data/gamedev/interfaces_v3/game_config.xml @@ -1230,8 +1230,15 @@ posref="BL TL" x="-20" y="-12" /> + + TexturesLoginInterface; std::vector TexturesLoginInterfaceDXTC; @@ -190,8 +190,6 @@ struct CClientConfig /// \name Inputs /// Use a hardware cursor - bool DisableDirectInput; - bool DisableDirectInputKeyboard; bool HardwareCursor; float HardwareCursorScale; // scale for hardware cursor bitmap (in ]0, 1]) float CursorSpeed; @@ -265,6 +263,9 @@ struct CClientConfig float GlobalWindPower; CVector GlobalWindDirection; + // FXAA + bool FXAA; + // Is bloom effect activated bool Bloom; bool SquareBloom; diff --git a/code/ryzom/client/src/connection.cpp b/code/ryzom/client/src/connection.cpp index 3a39dec1d..8b07cc7f2 100644 --- a/code/ryzom/client/src/connection.cpp +++ b/code/ryzom/client/src/connection.cpp @@ -31,6 +31,7 @@ // 3D Interface. #include "nel/3d/u_driver.h" #include "nel/3d/u_text_context.h" +#include // Game Share //#include "game_share/gd_time.h" // \todo GUIGUI : TO DELETE/CHANGE #include "game_share/gender.h" @@ -116,6 +117,8 @@ extern void saveMovieShooting(); extern void displaySpecialTextProgress(const char *text); extern bool InitMouseWithCursor(bool hardware); +extern bool SetMousePosFirstTime; + ///////////// // Globals // initialization occurs in the function : connection ///////////// @@ -203,9 +206,13 @@ void connectionRestaureVideoMode () if (ClientCfg.Width < 800) ClientCfg.Width = 800; if (ClientCfg.Height < 600) ClientCfg.Height = 600; - if ((ClientCfg.Windowed != mode.Windowed) || + if (StereoDisplay) + StereoDisplayAttached = StereoDisplay->attachToDisplay(); + + if (!StereoDisplayAttached && ( + (ClientCfg.Windowed != mode.Windowed) || (ClientCfg.Width != mode.Width) || - (ClientCfg.Height != mode.Height)) + (ClientCfg.Height != mode.Height))) { mode.Windowed = ClientCfg.Windowed; mode.Depth = uint8(ClientCfg.Depth); @@ -216,7 +223,7 @@ void connectionRestaureVideoMode () } // And setup hardware mouse if we have to - InitMouseWithCursor (ClientCfg.HardwareCursor); + InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); SetMouseFreeLook (); SetMouseCursor (); SetMouseSpeed (ClientCfg.CursorSpeed); @@ -251,6 +258,10 @@ void setOutGameFullScreen() // NB: don't setup fullscreen if player wants to play in window if (!ClientCfg.Local && ClientCfg.SelectCharacter == -1) { + if (StereoDisplayAttached) + StereoDisplay->detachFromDisplay(); + StereoDisplayAttached = false; + UDriver::CMode currMode; Driver->getCurrentScreenMode(currMode); UDriver::CMode wantedMode; @@ -267,6 +278,8 @@ void setOutGameFullScreen() { setVideoMode(wantedMode); } + + InitMouseWithCursor(ClientCfg.HardwareCursor && !StereoDisplayAttached); /* InitMouseWithCursor (true); Driver->showCursor(false); @@ -385,7 +398,7 @@ bool connection (const string &cookie, const string &fsaddr) // not initialized at login and remain hardware until here ... // Re-initialise the mouse (will be now in hardware mode, if required) - //InitMouseWithCursor (ClientCfg.HardwareCursor); // the return value of enableLowLevelMouse() has already been tested at startup + //InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); // the return value of enableLowLevelMouse() has already been tested at startup // no ui init if character selection is automatic //SetMouseFreeLook (); @@ -544,7 +557,8 @@ bool reconnection() if (ClientCfg.SelectCharacter == -1) { // Re-initialise the mouse (will be now in hardware mode, if required) - InitMouseWithCursor (ClientCfg.HardwareCursor); // the return value of enableLowLevelMouse() has already been tested at startup + SetMousePosFirstTime = true; + InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); // the return value of enableLowLevelMouse() has already been tested at startup // no ui init if character selection is automatic SetMouseFreeLook (); diff --git a/code/ryzom/client/src/events_listener.cpp b/code/ryzom/client/src/events_listener.cpp index 1d05f8a4e..89963a2ab 100644 --- a/code/ryzom/client/src/events_listener.cpp +++ b/code/ryzom/client/src/events_listener.cpp @@ -21,7 +21,6 @@ #include "events_listener.h" #include "nel/misc/events.h" -#include "nel/misc/game_device_events.h" #include "nel/misc/event_server.h" #include "release.h" #include "actions.h" @@ -29,11 +28,13 @@ #include "time_client.h" #include "input.h" #include "interface_v3/interface_manager.h" +#include "global.h" using namespace NLMISC; extern CActionsManager Actions; // Actions Manager. +extern bool MouseFreeLook; //--------------------------------------------------- // CEventsListener : @@ -82,7 +83,6 @@ CEventsListener::~CEventsListener() //--------------------------------------------------- void CEventsListener::addToServer(CEventServer& server) { - server.addListener(EventGDMouseMove, this); server.addListener(EventMouseMoveId, this); server.addListener(EventMouseDownId, this); server.addListener(EventMouseUpId, this); @@ -101,7 +101,6 @@ void CEventsListener::addToServer(CEventServer& server) //--------------------------------------------------- void CEventsListener::removeFromServer (CEventServer& server) { - server.removeListener(EventGDMouseMove, this); server.removeListener(EventMouseMoveId, this); server.removeListener(EventMouseDownId, this); server.removeListener(EventMouseUpId, this); @@ -113,6 +112,12 @@ void CEventsListener::removeFromServer (CEventServer& server) server.removeListener(EventSetFocusId, this); }// removeFromServer // +static bool s_MouseFreeLookReady = false; +static sint s_MouseFreeLookLastX; +static sint s_MouseFreeLookLastY; +static sint s_MouseFreeLookFrameX = 0; +static sint s_MouseFreeLookFrameY = 0; +static bool s_MouseFreeLookWaitCenter; //--------------------------------------------------- // operator() : @@ -148,20 +153,64 @@ void CEventsListener::operator()(const CEvent& event) { CAHManager::getInstance()->runActionHandler("enter_modal", NULL, "group=ui:interface:quit_dialog"); } - // Event from the Mouse (ANGLE) - if(event == EventGDMouseMove) - { - CGDMouseMove* mouseEvent=(CGDMouseMove*)&event; - // Mouse acceleration - sint dX = mouseEvent->X; - sint dY = ClientCfg.FreeLookInverted ? -mouseEvent->Y : mouseEvent->Y; - updateFreeLookPos((float) dX, (float) dY); - } // Event from the Mouse (MOVE) else if(event == EventMouseMoveId) { CEventMouseMove* mouseEvent=(CEventMouseMove*)&event; - updateCursorPos(mouseEvent->X, mouseEvent->Y); + if (!MouseFreeLook) + { + updateCursorPos(mouseEvent->X, mouseEvent->Y); + s_MouseFreeLookReady = false; + } + else + { + // Get in pixel space, centered + uint32 drW, drH; + Driver->getWindowSize(drW, drH); + float fX = mouseEvent->X; // from 0 to 1.0 + float fY = (ClientCfg.FreeLookInverted ? -mouseEvent->Y : mouseEvent->Y); + sint scX = (sint32)(fX * (float)drW) - ((sint32)drW >> 1); // in pixels, centered + sint scY = (sint32)(fY * (float)drH) - ((sint32)drH >> 1); + if (!s_MouseFreeLookReady) + { + float pfX = _MouseX; + float pfY = (ClientCfg.FreeLookInverted ? -_MouseY : _MouseY); + sint pscX = (sint32)(pfX * (float)drW) - ((sint32)drW >> 1); // in pixels, centered + sint pscY = (sint32)(pfY * (float)drH) - ((sint32)drH >> 1); + s_MouseFreeLookReady = true; + s_MouseFreeLookLastX = pscX; + s_MouseFreeLookLastY = pscY; + s_MouseFreeLookWaitCenter = false; + } + + // NOTE: No 0, 0 center mouse message in Windows (lower mouse message rate), but safe to assume any movement messages are requeued relative to our new position + // In case free look bugs on other platform, we may need to push in our own message on setMousePos for Windows + if (s_MouseFreeLookWaitCenter) // scX == 0 && scY == 0) + { + // Centered, set last to 0 + s_MouseFreeLookLastX = 0; + s_MouseFreeLookLastY = 0; + s_MouseFreeLookWaitCenter = false; + } + + // Get delta since last center + sint scXd = scX - s_MouseFreeLookLastX; + sint scYd = scY - s_MouseFreeLookLastY; + s_MouseFreeLookLastX = scX; + s_MouseFreeLookLastY = scY; + + s_MouseFreeLookFrameX += scXd; + s_MouseFreeLookFrameY += scYd; + // updateFreeLookPos is called in updateMouseSmoothing per frame + + // Center cursor + bool outsideBounds = ((abs(scX) > (drW >> 3)) || (abs(scY) > (drH >> 3))); + if (outsideBounds) + { + s_MouseFreeLookWaitCenter = true; + Driver->setMousePos(0.5f, 0.5f); + } + } } // Event from the Mouse (DOWN BUTTONS) else if(event == EventMouseDownId) @@ -233,16 +282,9 @@ void CEventsListener::updateMouseSmoothing() { if (_LastFreeLookUpdateDate != TimeInSec) { - if (ClientCfg.FreeLookSmoothingPeriod != 0.f && _MouseSmoothingOn) - { - // free look hasn't been updated that frame because there was no - // mouse move msg. - // mouse pos must be updated however because of smoothing - updateFreeLookPos(0, 0); - - - - } + updateFreeLookPos((float)s_MouseFreeLookFrameX, (float)s_MouseFreeLookFrameY); + s_MouseFreeLookFrameX = 0; + s_MouseFreeLookFrameY = 0; } } @@ -267,7 +309,6 @@ void CEventsListener::enableMouseSmoothing(bool on) // *************************************************************** void CEventsListener::updateFreeLookPos(float x, float y) { - if (ClientCfg.FreeLookSmoothingPeriod == 0 || !_MouseSmoothingOn) { _MouseDeltaAX = x * ClientCfg.FreeLookSpeed; diff --git a/code/ryzom/client/src/global.cpp b/code/ryzom/client/src/global.cpp index c965db43f..7c298ca58 100644 --- a/code/ryzom/client/src/global.cpp +++ b/code/ryzom/client/src/global.cpp @@ -25,21 +25,25 @@ using namespace NLMISC; // *************************************************************************** // Main System -NL3D::UDriver *Driver = 0; // The main 3D Driver +NL3D::UDriver *Driver = NULL; // The main 3D Driver NL3D::IStereoDisplay *StereoDisplay = NULL; // Stereo display NL3D::IStereoHMD *StereoHMD = NULL; // Head mount display -CSoundManager *SoundMngr = 0; // the sound manager +bool StereoDisplayAttached = false; // Is stereo display handling the display mode +CSoundManager *SoundMngr = NULL; // the sound manager NL3D::UMaterial GenericMat; // Generic Material -NL3D::UTextContext *TextContext = 0; // Context for all the text in the client. +NL3D::UTextContext *TextContext = NULL; // Context for all the text in the client. + +// Effects +NL3D::CFXAA *FXAA = NULL; // Main 3D Objects -NL3D::UScene *Scene = 0; -NL3D::UScene *SceneRoot = 0; -NL3D::UInstanceGroup *BackgroundIG = 0; -NL3D::ULandscape *Landscape = 0; -NL3D::UCloudScape *CloudScape = 0; +NL3D::UScene *Scene = NULL; +NL3D::UScene *SceneRoot = NULL; +NL3D::UInstanceGroup *BackgroundIG = NULL; +NL3D::ULandscape *Landscape = NULL; +NL3D::UCloudScape *CloudScape = NULL; NL3D::UCamera MainCam; -NL3D::UVisualCollisionManager *CollisionManager = 0; +NL3D::UVisualCollisionManager *CollisionManager = NULL; #ifdef USE_WATER_ENV_MAP CWaterEnvMapRdr WaterEnvMapRdr; NL3D::UWaterEnvMap *WaterEnvMap = NULL; @@ -58,7 +62,7 @@ NLMISC::CMatrix InvMainSceneViewMatrix; // Matrix to transform from camera s // Misc bool InitCloudScape = true; // tells that the cloud scape must be reinitialized -CEntityAnimationManager *EAM = 0; +CEntityAnimationManager *EAM = NULL; CProgress ProgressBar; TBackground LoadingBackground = StartBackground; string LoadingMusic; diff --git a/code/ryzom/client/src/global.h b/code/ryzom/client/src/global.h index 5879eeaec..de9aa6a73 100644 --- a/code/ryzom/client/src/global.h +++ b/code/ryzom/client/src/global.h @@ -42,6 +42,7 @@ namespace NL3D class UWaterEnvMap; class IStereoDisplay; class IStereoHMD; + class CFXAA; } class CEntityAnimationManager; @@ -81,10 +82,14 @@ const float ExtraZoneLoadingVision = 100.f; extern NL3D::UDriver *Driver; // The main 3D Driver extern NL3D::IStereoDisplay *StereoDisplay; // Stereo display extern NL3D::IStereoHMD *StereoHMD; // Head mount display +extern bool StereoDisplayAttached; // Is stereo display handling the display mode extern CSoundManager *SoundMngr; // the sound manager extern NL3D::UMaterial GenericMat; // Generic Material extern NL3D::UTextContext *TextContext; // Context for all the text in the client. +// Effects +extern NL3D::CFXAA *FXAA; + // Main 3D Objects extern NL3D::UScene *Scene; extern NL3D::UScene *SceneRoot; diff --git a/code/ryzom/client/src/init.cpp b/code/ryzom/client/src/init.cpp index 809232983..1644f7e2d 100644 --- a/code/ryzom/client/src/init.cpp +++ b/code/ryzom/client/src/init.cpp @@ -616,10 +616,16 @@ void initStereoDisplayDevice() std::vector devices; listStereoDisplayDevices(devices); CStereoDeviceInfo *deviceInfo = NULL; - if (ClientCfg.VRDisplayDevice == std::string("Auto") - && devices.begin() != devices.end()) + if (ClientCfg.VRDisplayDevice == std::string("Auto")) { - deviceInfo = &devices[0]; + for (std::vector::iterator it(devices.begin()), end(devices.end()); it != end; ++it) + { + if ((*it).AllowAuto) + { + deviceInfo = &(*it); + break; + } + } } else { @@ -1069,34 +1075,6 @@ void prelogInit() FPU_CHECKER_ONCE - // Test mouse & keyboard low-level mode, if DisableDirectInput not set. - // In case of failure, exit the client. - // In case of success, set it back to normal mode, to provide for the user - // the ability to manually set the firewall's permissions when the client connects. - // The low-level mode will actually be set when "launching" (after loading). - if (!ClientCfg.DisableDirectInput) - { - // Test mouse and set back to normal mode - if (!Driver->enableLowLevelMouse (true, ClientCfg.HardwareCursor)) - { - ExitClientError (CI18N::get ("can_t_initialise_the_mouse").toUtf8 ().c_str ()); - // ExitClientError() call exit() so the code after is never called - return; - } - Driver->enableLowLevelMouse (false, ClientCfg.HardwareCursor); - - // Test keyboard and set back to normal mode - // NB : keyboard will be initialized later now - /*if (!Driver->enableLowLevelKeyboard (true)) - { - ExitClientError (CI18N::get ("can_t_initialise_the_keyboard").toUtf8 ().c_str ()); - // ExitClientError() call exit() so the code after is never called - return; - } - Driver->enableLowLevelKeyboard (false); - */ - } - // Set the monitor color properties CMonitorColorProperties monitorColor; for ( uint i=0; i<3; i++) @@ -1189,7 +1167,7 @@ void prelogInit() CBloomEffect::getInstance().setDriver(Driver); // init bloom effect - CBloomEffect::getInstance().init(driver != UDriver::Direct3d); + CBloomEffect::getInstance().init(); if (StereoDisplay) // VR_CONFIG { diff --git a/code/ryzom/client/src/init_main_loop.cpp b/code/ryzom/client/src/init_main_loop.cpp index 60f4fedb9..537f322f8 100644 --- a/code/ryzom/client/src/init_main_loop.cpp +++ b/code/ryzom/client/src/init_main_loop.cpp @@ -40,6 +40,8 @@ #include "nel/3d/u_cloud_scape.h" #include "nel/3d/u_shape_bank.h" #include "nel/3d/u_water_env_map.h" +#include "nel/3d/material.h" +#include "nel/3d/fxaa.h" // Sound #include "nel/sound/u_audio_mixer.h" // Client @@ -125,6 +127,8 @@ namespace R2 extern bool ReloadUIFlag; } +extern bool SetMousePosFirstTime; + extern EGSPD::CSeason::TSeason ManualSeasonValue; UTextureFile *LoadingBitmap = NULL; UTextureFile *LoadingBitmapFull = NULL; @@ -563,6 +567,9 @@ void initMainLoop() if(Scene == 0) nlerror("initMainLoop : Cannot create a Scene."); + // create effects + if (ClientCfg.FXAA && !FXAA) FXAA = new NL3D::CFXAA(Driver); + // use this scene for bloom effect CBloomEffect::getInstance().setScene(Scene); @@ -1253,7 +1260,8 @@ void initMainLoop() // NLMEMORY::CheckHeap (true); // Re-initialise the mouse (will be now in hardware mode, if required) - InitMouseWithCursor (ClientCfg.HardwareCursor); // the return value of enableLowLevelMouse() has already been tested at startup + SetMousePosFirstTime = true; + InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); // the return value of enableLowLevelMouse() has already been tested at startup // Re-initialise the keyboard, now in low-level mode, if required // NB nico : done at end of loading @@ -1496,6 +1504,7 @@ void initWelcomeWindow() // *************************************************************************** +// NOTE: This feature is not really used anymore, it is a patch transition void initHardwareCursor(bool secondCall) { CInterfaceManager * pIM = CInterfaceManager::getInstance(); @@ -1571,6 +1580,7 @@ void initBloomConfigUI() if(group) group->setDefaultContextHelp(CI18N::get("uiFxTooltipBloom")); + ClientCfg.writeBool("FXAA", false); ClientCfg.writeBool("Bloom", false); ClientCfg.writeBool("SquareBloom", false); ClientCfg.writeInt("DensityBloom", 0); diff --git a/code/ryzom/client/src/input.cpp b/code/ryzom/client/src/input.cpp index eff4e2bc9..6d0834f07 100644 --- a/code/ryzom/client/src/input.cpp +++ b/code/ryzom/client/src/input.cpp @@ -21,6 +21,7 @@ ///////////// #include "stdpch.h" // Client +#include "global.h" #include "actions.h" #include "input.h" #include "interface_v3/interface_manager.h" @@ -30,7 +31,6 @@ // 3D #include "nel/3d/u_driver.h" // Misc -#include "nel/misc/mouse_device.h" #include "nel/misc/mouse_smoother.h" #include "nel/misc/system_utils.h" // Game Share @@ -54,7 +54,6 @@ extern CActionsManager Actions; // Actions Manager. //////////// // GLOBAL // //////////// -IMouseDevice *MouseDevice = NULL; bool MouseHardware = false; bool MouseFreeLook = false; float MouseCursorSpeed = 1.f; @@ -81,93 +80,40 @@ bool InitMouseWithCursor (bool hardware) { Driver->showCursor(false); - // First init ? - if (MouseDevice) - { - // No.. change soft to hard or hard to soft ? - if (hardware ^ MouseHardware) - { - // Ok, reinit the mouse - Driver->enableLowLevelMouse (false, false); - MouseDevice = NULL; - MouseHardware = false; - } - } - // Get the new mouse state MouseHardware = hardware; CViewPointer::setHWMouse( hardware ); - // Reinit ? - if (MouseDevice == NULL) + // Update mouse information + UpdateMouse (); + + if (InitMouseFirstTime) { - if (!ClientCfg.DisableDirectInput) + InitMouseFirstTime = false; + } + else + { + if (!MouseFreeLook) { - // mouse capture not taken in account for hardware mouse - MouseDevice = Driver->enableLowLevelMouse(true, hardware); - if (!MouseDevice) - return false; - } - - // Update mouse information - UpdateMouse (); - - if (InitMouseFirstTime) - { - InitMouseFirstTime = false; - } - else - { - if (!MouseFreeLook) + // Get the current mouse position + CInterfaceManager *pIm = CInterfaceManager::getInstance(); + CViewPointer *vp = static_cast< CViewPointer* >( CWidgetManager::getInstance()->getPointer() ); + Driver->showCursor(hardware); + if (vp) { - // Get the current mouse position - if (hardware) + float x = (float) vp->getX(); + float y = (float) vp->getY(); + // First, hide the hardware mouse + uint width = Driver->getWindowWidth(); + uint height = Driver->getWindowHeight(); + if (SetMousePosFirstTime) { - Driver->showCursor(true); - - CViewPointer *pointer = static_cast< CViewPointer* >( CWidgetManager::getInstance()->getPointer() ); - if (pointer) - { - float x = (float)pointer->getX()/(float)Driver->getWindowWidth(); - float y = (float)pointer->getY()/(float)Driver->getWindowHeight(); - - if (SetMousePosFirstTime) - { - SetMousePosFirstTime = false; - } - else - { - Driver->setMousePos(x, y); - nlwarning("mouse pos %f,%f", x, y); - } - - } - } - else - { - CInterfaceManager *pIm = CInterfaceManager::getInstance(); - CViewPointer *vp = static_cast< CViewPointer* >( CWidgetManager::getInstance()->getPointer() ); - Driver->showCursor(false); SetMousePosFirstTime = false; - if (vp) - { - float x = (float) vp->getX(); - float y = (float) vp->getY(); - // First, hide the hardware mouse - if (MouseDevice) - { - MouseDevice->setMousePos(x, y); - } - else - { - uint width = Driver->getWindowWidth(); - uint height = Driver->getWindowHeight(); - if (width != 0 && height != 0) - { - Driver->setMousePos(x / width, y / height); - } - } - } + } + else if (width != 0 && height != 0) + { + nlwarning("mouse pos %u, %u", x, y); + Driver->setMousePos(x / width, y / height); } } } @@ -187,45 +133,6 @@ bool IsMouseCursorHardware () // Set the mouse mode. Call this method once per frame to update window size void UpdateMouse () { - // Freelook ? - if (MouseFreeLook) - { - // Raw mode - if (MouseDevice) - { - MouseDevice->setMessagesMode(IMouseDevice::RawMode); - MouseDevice->setMouseAcceleration(ClientCfg.FreeLookAcceleration); - } - else - { - // no mouse device implementation on X11 and Cocoa, emulate raw mode - Driver->emulateMouseRawMode(true); - } - } - else - { - // Set the mouse properties - if (MouseDevice) - { - // Get the driver size - uint32 width, height; - Driver->getWindowSize(width, height); - - MouseDevice->setMessagesMode(IMouseDevice::NormalMode); - MouseDevice->setMouseMode(IMouseDevice::XAxis, IMouseDevice::Clamped); - MouseDevice->setMouseMode(IMouseDevice::YAxis, IMouseDevice::Clamped); - CRect window (0, 0, width, height); - MouseDevice->setMouseFrame(window); - MouseDevice->setFactors(1.f/std::max((float)width, 1.0f), 1.f/std::max((float)height, 1.0f)); - MouseDevice->setMouseSpeed(MouseCursorSpeed); - MouseDevice->setMouseAcceleration(MouseCursorAcceleration); - } - else - { - // no mouse device implementation on X11 and Cocoa, emulate raw mode - Driver->emulateMouseRawMode(false); - } - } if (!Driver->isSystemCursorCaptured()) { DownMouseButtons = 0; @@ -303,19 +210,7 @@ void SetMouseCursor (bool updatePos) if (updatePos) { - if (MouseDevice) - { - MouseDevice->setMousePos((float)ix, (float)iy); - } - else - { - Driver->setMousePos(x, y); - } - - if (MouseHardware) - { - Driver->setMousePos(x, y); - } + Driver->setMousePos(x, y); } // Update the interface pointer @@ -404,25 +299,18 @@ CNiceInputAuto::CNiceInputAuto() { if (_Count == 0) { - - Driver->enableLowLevelMouse(false, false); // but ignore direct input (win 32 msg only) - - Driver->setCursor("curs_default.tga", CRGBA::White, 0, 0x15, 0x18); Driver->showCursor(true); // keep cursor visible in windowed mode - MouseDevice = NULL; - Driver->enableLowLevelKeyboard (false); } - ++ _Count; + ++_Count; } CNiceInputAuto::~CNiceInputAuto() { - -- _Count; + --_Count; nlassert(_Count >= 0); if (_Count == 0) { - InitMouseWithCursor (ClientCfg.HardwareCursor); - Driver->enableLowLevelKeyboard (!ClientCfg.DisableDirectInputKeyboard); // the return value has already been tested at startup + InitMouseWithCursor(ClientCfg.HardwareCursor && !StereoDisplayAttached); } } diff --git a/code/ryzom/client/src/interface_v3/input_handler_manager.cpp b/code/ryzom/client/src/interface_v3/input_handler_manager.cpp index 62eac876c..48582652a 100644 --- a/code/ryzom/client/src/interface_v3/input_handler_manager.cpp +++ b/code/ryzom/client/src/interface_v3/input_handler_manager.cpp @@ -20,7 +20,6 @@ #include "nel/misc/i_xml.h" #include "nel/misc/file.h" -#include "nel/misc/game_device_events.h" #include "nel/misc/xml_auto_ptr.h" @@ -92,7 +91,6 @@ void CInputHandlerManager::addToServer(NLMISC::CEventServer * server) _EventServer = server; // System - server->addListener(EventGDMouseMove, this); server->addListener(EventDestroyWindowId, this); server->addListener(EventCloseWindowId, this); server->addListener(EventSetFocusId, this); @@ -117,7 +115,6 @@ void CInputHandlerManager::addToServer(NLMISC::CEventServer * server) void CInputHandlerManager::release() { // System - _EventServer->removeListener(EventGDMouseMove, this); _EventServer->removeListener(EventDestroyWindowId, this); _EventServer->removeListener(EventCloseWindowId, this); _EventServer->removeListener(EventSetFocusId, this); @@ -304,7 +301,7 @@ void CInputHandlerManager::operator ()(const NLMISC::CEvent &event) handled |= R2::getEditor().handleEvent(eventDesc); } } - handled |= inputHandler.handleMouseButtonDownEvent( event ); + handled |= inputHandler.handleMouseButtonDownEvent( event ); } // button up ? else if (event==EventMouseUpId) diff --git a/code/ryzom/client/src/landscape_poly_drawer.h b/code/ryzom/client/src/landscape_poly_drawer.h index 73d7fcadc..865112223 100644 --- a/code/ryzom/client/src/landscape_poly_drawer.h +++ b/code/ryzom/client/src/landscape_poly_drawer.h @@ -97,7 +97,9 @@ private: // renderScene is called in main loop. It can called beginRenderLandscapePolyPart and renderLandscapePolyPart // methods. - friend void renderScene(); + friend void beginRenderScene(); + friend void drawRenderScene(bool wantTraversals, bool keepTraversals); + friend void endRenderScene(bool keepTraversals); // Enable stencil test and initialize function and operation of stencil at the beginning of renderScene method, // before opaque render of canopy and main scene parts. diff --git a/code/ryzom/client/src/login.cpp b/code/ryzom/client/src/login.cpp index 210afcea9..091e24a80 100644 --- a/code/ryzom/client/src/login.cpp +++ b/code/ryzom/client/src/login.cpp @@ -73,6 +73,8 @@ using namespace std; // *************************************************************************** +extern bool SetMousePosFirstTime; + vector Shards; string LoginLogin, LoginPassword, ClientApp, Salt; @@ -114,7 +116,7 @@ vector R2PatchURLs; #define CTRL_EDITBOX_CREATEACCOUNT_LOGIN "ui:login:create_account:content:submit_gr:eb_login:eb" #define CTRL_EDITBOX_CREATEACCOUNT_PASSWORD "ui:login:create_account:content:submit_gr:eb_password:eb" #define CTRL_EDITBOX_CREATEACCOUNT_CONFIRMPASSWORD "ui:login:create_account:content:submit_gr:eb_confirm_password:eb" -#define CTRL_EDITBOX_CREATEACCOUNT_EMAIL "ui:login:create_account:content:submit_gr:eb_email:eb" +#define CTRL_EDITBOX_CREATEACCOUNT_EMAIL "ui:login:create_account:content:submit_gr:eb_email:eb" #define UI_VARIABLES_SCREEN_CHECKPASS 0 #define UI_VARIABLES_SCREEN_SHARDDISP 1 @@ -857,16 +859,15 @@ bool login() IngameDbMngr.flushObserverCalls(); NLGUI::CDBManager::getInstance()->flushObserverCalls(); - bool tmpDI = ClientCfg.DisableDirectInput; - ClientCfg.DisableDirectInput = true; + SetMousePosFirstTime = true; InitMouseWithCursor(false); Driver->showCursor (false); SetMouseFreeLook (); SetMouseCursor (false); SetMouseSpeed (ClientCfg.CursorSpeed); SetMouseAcceleration (ClientCfg.CursorAcceleration); - InitMouseWithCursor (ClientCfg.HardwareCursor); - ClientCfg.DisableDirectInput = tmpDI; + SetMousePosFirstTime = true; + InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); // if (ClientCfg.TestBrowser) // { @@ -1989,6 +1990,7 @@ class CAHInitResLod : public IActionHandler CfgPresetList.push_back(pair("NbMaxSkeletonNotCLod", false)); CfgPresetList.push_back(pair("CharacterFarClip", true)); + CfgPresetList.push_back(pair("FXAA", false)); CfgPresetList.push_back(pair("Bloom", false)); CfgPresetList.push_back(pair("SquareBloom", false)); CfgPresetList.push_back(pair("DensityBloom", true)); @@ -2410,7 +2412,7 @@ bool initCreateAccount() rulesGr->setActive(false); // must be done after hide rules - CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_CREATEACCOUNT_LOGIN "|select_all=false"); + CAHManager::getInstance()->runActionHandler("set_keyboard_focus", NULL, "target=" CTRL_EDITBOX_CREATEACCOUNT_LOGIN "|select_all=false"); } diff --git a/code/ryzom/client/src/main_loop.cpp b/code/ryzom/client/src/main_loop.cpp index 0d000310d..1ac6a4a0c 100644 --- a/code/ryzom/client/src/main_loop.cpp +++ b/code/ryzom/client/src/main_loop.cpp @@ -43,6 +43,9 @@ #include "nel/3d/u_instance_material.h" #include "nel/3d/u_cloud_scape.h" #include "nel/3d/stereo_hmd.h" +#include "nel/3d/render_target_manager.h" +#include "nel/3d/driver_user.h" +#include "nel/3d/fxaa.h" // game share #include "game_share/brick_types.h" #include "game_share/light_cycle.h" @@ -165,7 +168,6 @@ using namespace std; // EXTERN // //////////// extern UDriver *Driver; -extern IMouseDevice *MouseDevice; extern UScene *Scene; extern UScene *SceneRoot; extern ULandscape *Landscape; @@ -421,9 +423,9 @@ void beginRenderMainScenePart() { Scene->beginPartRender(); } -void endRenderMainScenePart() +void endRenderMainScenePart(bool keepTraversals) { - Scene->endPartRender(true); + Scene->endPartRender(!keepTraversals, true, keepTraversals); } void beginRenderSkyPart() @@ -460,7 +462,7 @@ static void renderCanopyPart(UScene::TRenderPart renderPart) // *************************************************************************************************************************** // Render a part of the main scene -static void renderMainScenePart(UScene::TRenderPart renderPart) +static void renderMainScenePart(UScene::TRenderPart renderPart, bool wantTraversals, bool keepTraversals) { H_AUTO_USE ( RZ_Client_Main_Loop_Render_Main ) Driver->setDepthRange(0.f, CANOPY_DEPTH_RANGE_START); @@ -472,7 +474,7 @@ static void renderMainScenePart(UScene::TRenderPart renderPart) { MainFogState.setupInDriver (*Driver); } - Scene->renderPart(renderPart); + Scene->renderPart(renderPart, true, wantTraversals, keepTraversals); } @@ -562,13 +564,15 @@ void clearBuffers() void renderScene(bool forceFullDetail, bool bloom) { + CTextureUser *effectRenderTarget = NULL; if (bloom) { // set bloom parameters before applying bloom effect CBloomEffect::getInstance().setSquareBloom(ClientCfg.SquareBloom); CBloomEffect::getInstance().setDensityBloom((uint8)ClientCfg.DensityBloom); - // init bloom - CBloomEffect::getInstance().initBloom(); + + // init effect render target + Driver->beginDefaultRenderTarget(); } if (forceFullDetail) { @@ -576,7 +580,7 @@ void renderScene(bool forceFullDetail, bool bloom) s_ForceFullDetail.set(); } clearBuffers(); - renderScene(); + doRenderScene(true, false); if (forceFullDetail) { s_ForceFullDetail.restore(); @@ -584,8 +588,10 @@ void renderScene(bool forceFullDetail, bool bloom) if (bloom) { // apply bloom effect - CBloomEffect::getInstance().endBloom(); - CBloomEffect::getInstance().endInterfacesDisplayBloom(); + CBloomEffect::getInstance().applyBloom(); + + // draw final result to backbuffer + Driver->endDefaultRenderTarget(Scene); } } @@ -661,7 +667,7 @@ void updateWeather() updateClouds(); } #endif - + ContinentMngr.getFogState(MainFog, LightCycleManager.getLightLevel(), LightCycleManager.getLightDesc().DuskRatio, LightCycleManager.getState(), View.viewPos(), MainFogState); // TODO: ZBuffer clear was originally before this, but should not be necessary normally. @@ -687,7 +693,7 @@ void updateWeather() Driver->setPolygonMode(oldMode); } #endif - + // Update new sky s_SkyMode = NoSky; if (ContinentMngr.cur() && !ContinentMngr.cur()->Indoor) @@ -713,9 +719,7 @@ void updateWeather() } } -// *************************************************************************************************************************** -// Render all scenes -void renderScene() +void beginRenderScene() { // Update Filter Flags Scene->enableElementRender(UScene::FilterAllMeshNoVP, Filter3D[FilterMeshNoVP]); @@ -737,28 +741,45 @@ void renderScene() beginRenderCanopyPart(); beginRenderMainScenePart(); beginRenderSkyPart(); +} + +void drawRenderScene(bool wantTraversals, bool keepTraversals) +{ // Render part // WARNING: always must begin rendering with at least UScene::RenderOpaque, // else dynamic shadows won't work renderCanopyPart(UScene::RenderOpaque); - renderMainScenePart(UScene::RenderOpaque); + renderMainScenePart(UScene::RenderOpaque, wantTraversals, keepTraversals); // render of polygons on landscape CLandscapePolyDrawer::getInstance().renderLandscapePolyPart(); if (s_SkyMode != NoSky) renderSkyPart((UScene::TRenderPart) (UScene::RenderOpaque | UScene::RenderTransparent)); renderCanopyPart((UScene::TRenderPart) (UScene::RenderTransparent | UScene::RenderFlare)); - renderMainScenePart((UScene::TRenderPart) (UScene::RenderTransparent | UScene::RenderFlare)); + renderMainScenePart((UScene::TRenderPart) (UScene::RenderTransparent | UScene::RenderFlare), wantTraversals, keepTraversals); if (s_SkyMode == NewSky) renderSkyPart(UScene::RenderFlare); +} + +void endRenderScene(bool keepTraversals) +{ // End Part Rendering endRenderSkyPart(); - endRenderMainScenePart(); + endRenderMainScenePart(keepTraversals); endRenderCanopyPart(); // reset depth range Driver->setDepthRange(0.f, CANOPY_DEPTH_RANGE_START); } +// *************************************************************************************************************************** +// Render all scenes +void doRenderScene(bool wantTraversals, bool keepTraversals) +{ + beginRenderScene(); + drawRenderScene(wantTraversals, keepTraversals); + endRenderScene(keepTraversals); +} + // *************************************************************************** class CMusicFader @@ -1387,8 +1408,20 @@ bool mainLoop() MainCam.setRotQuat(View.currentViewQuat()); if (StereoHMD) { + CMatrix camMatrix; + camMatrix.translate(MainCam.getMatrix().getPos()); + CVector dir = MainCam.getMatrix().getJ(); + dir.z = 0; + dir.normalize(); + if (dir.y < 0) + camMatrix.rotateZ(float(NLMISC::Pi+asin(dir.x))); + else + camMatrix.rotateZ(float(NLMISC::Pi+NLMISC::Pi-asin(dir.x))); + + StereoHMD->setInterfaceMatrix(camMatrix); + NLMISC::CQuat hmdOrient = StereoHMD->getOrientation(); - NLMISC::CMatrix camMatrix = MainCam.getMatrix(); + // NLMISC::CMatrix camMatrix = MainCam.getMatrix(); NLMISC::CMatrix hmdMatrix; hmdMatrix.setRot(hmdOrient); NLMISC::CMatrix posMatrix; // minimal head modeling, will be changed in the future @@ -1396,8 +1429,15 @@ bool mainLoop() NLMISC::CMatrix mat = ((camMatrix * hmdMatrix) * posMatrix); MainCam.setPos(mat.getPos()); MainCam.setRotQuat(mat.getRot()); + + if (true) // TODO: ClientCfg.Headphone + { + // NOTE: non-(StereoHMD+Headphone) impl in user_entity.cpp + SoundMngr->setListenerPos(mat.getPos()); // TODO: Move ears back ... :) + SoundMngr->setListenerOrientation(mat.getJ(), mat.getK()); + } } - if (StereoDisplay) + if (StereoDisplay) { StereoDisplay->updateCamera(0, &MainCam); if (SceneRoot) @@ -1596,14 +1636,31 @@ bool mainLoop() { // Update water env map (happens when continent changed etc) updateWaterEnvMap(); - + // Update weather updateWeather(); } } - + uint i = 0; - uint bloomStage = 0; + CTextureUser *effectRenderTarget = NULL; + bool haveEffects = Render && Driver->getPolygonMode() == UDriver::Filled + && (ClientCfg.Bloom || FXAA); + bool defaultRenderTarget = false; + if (haveEffects) + { + if (!StereoDisplay) + { + Driver->beginDefaultRenderTarget(); + defaultRenderTarget = true; + } + if (ClientCfg.Bloom) + { + CBloomEffect::getInstance().setSquareBloom(ClientCfg.SquareBloom); + CBloomEffect::getInstance().setDensityBloom((uint8)ClientCfg.DensityBloom); + } + } + bool fullDetail = false; while ((!StereoDisplay && i == 0) || (StereoDisplay && StereoDisplay->nextPass())) { ++i; @@ -1635,60 +1692,68 @@ bool mainLoop() // Commit camera changes commitCamera(); - + ////////////////////////// // RENDER THE FRAME 3D // ////////////////////////// bool stereoRenderTarget = (StereoDisplay != NULL) && StereoDisplay->beginRenderTarget(); - + if (!StereoDisplay || StereoDisplay->wantClear()) { - if (Render) - { - if (ClientCfg.Bloom) - { - nlassert(bloomStage == 0); - // set bloom parameters before applying bloom effect - CBloomEffect::getInstance().setSquareBloom(ClientCfg.SquareBloom); - CBloomEffect::getInstance().setDensityBloom((uint8)ClientCfg.DensityBloom); - // start bloom effect (just before the first scene element render) - CBloomEffect::instance().initBloom(); - bloomStage = 1; - } - } - // Clear buffers clearBuffers(); } if (!StereoDisplay || StereoDisplay->wantScene()) { - if (!ClientCfg.Light) + if (!ClientCfg.Light && Render) { - // Render - if(Render) + if (!StereoDisplay || StereoDisplay->isSceneFirst()) { // nb : force full detail if a screenshot is asked // todo : move outside render code - bool fullDetail = ScreenshotRequest != ScreenshotRequestNone && ClientCfg.ScreenShotFullDetail; - if (fullDetail) + if (!fullDetail) { - s_ForceFullDetail.backup(); - s_ForceFullDetail.set(); + fullDetail = ScreenshotRequest != ScreenshotRequestNone && ClientCfg.ScreenShotFullDetail; + if (fullDetail) + { + s_ForceFullDetail.backup(); + s_ForceFullDetail.set(); + } } - - // Render scene - renderScene(); + } + // Render scene + bool wantTraversals = !StereoDisplay || StereoDisplay->isSceneFirst(); + bool keepTraversals = StereoDisplay && !StereoDisplay->isSceneLast(); + doRenderScene(wantTraversals, keepTraversals); + + if (!StereoDisplay || StereoDisplay->isSceneLast()) + { if (fullDetail) { s_ForceFullDetail.restore(); + fullDetail = false; } } } } + if (!StereoDisplay || StereoDisplay->wantSceneEffects()) + { + if (!ClientCfg.Light && Render && haveEffects) + { + if (StereoDisplay) Driver->setViewport(NL3D::CViewport()); + UCamera pCam = Scene->getCam(); + Driver->setMatrixMode2D11(); + if (FXAA) FXAA->applyEffect(); + if (ClientCfg.Bloom) CBloomEffect::instance().applyBloom(); + Driver->setMatrixMode3D(pCam); + if (StereoDisplay) Driver->setViewport(StereoDisplay->getCurrentViewport()); + } + } + if (!StereoDisplay || StereoDisplay->wantInterface3D()) { if (!ClientCfg.Light) @@ -1696,15 +1761,6 @@ bool mainLoop() // Render if (Render) { - if (ClientCfg.Bloom && bloomStage == 1) - { - // End the actual bloom effect visible in the scene. - if (StereoDisplay) Driver->setViewport(NL3D::CViewport()); - CBloomEffect::instance().endBloom(); - if (StereoDisplay) Driver->setViewport(StereoDisplay->getCurrentViewport()); - bloomStage = 2; - } - // for that frame and // tmp : display height grid //static volatile bool displayHeightGrid = true; @@ -1823,14 +1879,14 @@ bool mainLoop() // special case in OpenGL : all scene has been display in render target, // now, final texture is display with a quad - if (!ClientCfg.Light && ClientCfg.Bloom && Render && bloomStage == 2) + /*if (!ClientCfg.Light && ClientCfg.Bloom && Render && bloomStage == 2) // NO VR BLOOMZ { // End bloom effect system after drawing the 3d interface (z buffer related). if (StereoDisplay) Driver->setViewport(NL3D::CViewport()); CBloomEffect::instance().endInterfacesDisplayBloom(); if (StereoDisplay) Driver->setViewport(StereoDisplay->getCurrentViewport()); bloomStage = 0; - } + }*/ } { @@ -2144,6 +2200,12 @@ bool mainLoop() } } /* stereo pass */ + if (defaultRenderTarget) + { + // draw final result to backbuffer + Driver->endDefaultRenderTarget(Scene); + } + // Draw to screen. static CQuat MainCamOri; if (FirstFrame) @@ -2446,7 +2508,7 @@ bool mainLoop() connectionState = NetMngr.getConnectionState(); CLuaManager::getInstance().executeLuaScript("game:onFarTpEnd()"); - } + } /////////////// // <- FAR_TP // /////////////// @@ -3184,7 +3246,7 @@ NLMISC_COMMAND(debugUI, "Debug the ui : show/hide quads of bboxs and hotspots", else fromString(args[0], on); } - + CGroupCell::setDebugUICell( on ); DebugUIView = on; DebugUICtrl = on; diff --git a/code/ryzom/client/src/main_loop.h b/code/ryzom/client/src/main_loop.h index 21f64d37e..93e4db36d 100644 --- a/code/ryzom/client/src/main_loop.h +++ b/code/ryzom/client/src/main_loop.h @@ -29,7 +29,7 @@ const uint NUM_MISSION_OPTIONS = 8; bool mainLoop(); // render all -void renderScene(); +void doRenderScene(bool wantTraversals, bool keepTraversals); void renderScene(bool forceFullDetail, bool bloom); void setDefaultChatWindow(CChatWindow *defaultChatWindow); diff --git a/code/ryzom/client/src/main_loop_utilities.cpp b/code/ryzom/client/src/main_loop_utilities.cpp index 194810ea9..cdd3f8394 100644 --- a/code/ryzom/client/src/main_loop_utilities.cpp +++ b/code/ryzom/client/src/main_loop_utilities.cpp @@ -19,6 +19,8 @@ #include #include +#include +#include #include "game_share/scenario_entry_points.h" @@ -57,8 +59,22 @@ void updateFromClientCfg() ))) { nldebug("Apply VR device change"); + // detach display mode + if (StereoDisplay && StereoDisplayAttached) + StereoDisplay->detachFromDisplay(); + StereoDisplayAttached = false; + // re-init releaseStereoDisplayDevice(); initStereoDisplayDevice(); + // try attach display mode + if (StereoDisplay) + StereoDisplayAttached = StereoDisplay->attachToDisplay(); + // set latest config display mode if not attached + if (!StereoDisplayAttached) + setVideoMode(UDriver::CMode(ClientCfg.Width, ClientCfg.Height, (uint8)ClientCfg.Depth, + ClientCfg.Windowed, ClientCfg.Frequency)); + // force software cursor when attached + InitMouseWithCursor(ClientCfg.HardwareCursor && !StereoDisplayAttached); } // GRAPHICS - GENERAL @@ -69,8 +85,11 @@ void updateFromClientCfg() (ClientCfg.Depth != LastClientCfg.Depth) || (ClientCfg.Frequency != LastClientCfg.Frequency)) { - setVideoMode(UDriver::CMode(ClientCfg.Width, ClientCfg.Height, (uint8)ClientCfg.Depth, - ClientCfg.Windowed, ClientCfg.Frequency)); + if (!StereoDisplayAttached) + { + setVideoMode(UDriver::CMode(ClientCfg.Width, ClientCfg.Height, (uint8)ClientCfg.Depth, + ClientCfg.Windowed, ClientCfg.Frequency)); + } } if (ClientCfg.DivideTextureSizeBy2 != LastClientCfg.DivideTextureSizeBy2) @@ -218,6 +237,22 @@ void updateFromClientCfg() } } + //--------------------------------------------------- + if (ClientCfg.FXAA != LastClientCfg.FXAA) + { + if (ClientCfg.FXAA) + { + nlassert(!FXAA); + FXAA = new NL3D::CFXAA(Driver); + } + else + { + nlassert(FXAA); + delete FXAA; + FXAA = NULL; + } + } + // GRAPHICS - CHARACTERS //--------------------------------------------------- if (ClientCfg.SkinNbMaxPoly != LastClientCfg.SkinNbMaxPoly) @@ -259,7 +294,7 @@ void updateFromClientCfg() { if (ClientCfg.HardwareCursor != IsMouseCursorHardware()) { - InitMouseWithCursor (ClientCfg.HardwareCursor); + InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); } } diff --git a/code/ryzom/client/src/motion/user_controls.cpp b/code/ryzom/client/src/motion/user_controls.cpp index 527bfb5d4..285848120 100644 --- a/code/ryzom/client/src/motion/user_controls.cpp +++ b/code/ryzom/client/src/motion/user_controls.cpp @@ -414,7 +414,6 @@ void CUserControls::keyboardRotationCameraLR (bool left, bool right) _RotateCameraLRVelocity = 0; } - //----------------------------------------------- // getMouseAngleMove //----------------------------------------------- @@ -424,13 +423,9 @@ void CUserControls::getMouseAngleMove(float &dx, float &dy) dy = 0.0f; // The mouse may still "StandardMove" ie through a CEventMouseMove - // This can happens cause DirectInputDisabled, or because of the - // "Rotation Anti-Lag system" which start to rotate before the mouse is hid - // and message mode passed to RawMode - // - // On X11 and Cocoa, there is no MouseDevice, do it without. - - extern IMouseDevice *MouseDevice; + // This can happen because of the "Rotation Anti-Lag system" which + // start to rotate before the mouse is hid and message mode passed + // to updateFreeLookPos // if the mouse position changed if( EventsListener.getMousePosX() != _LastFrameMousePosX || @@ -441,28 +436,23 @@ void CUserControls::getMouseAngleMove(float &dx, float &dy) float dmpy= EventsListener.getMousePosY() - _LastFrameMousePosY; // simulate mickeys mode if there is a mouse device - if (MouseDevice) - MouseDevice->convertStdMouseMoveInMickeys(dmpx, dmpy); - else - { - dmpx *= (float)Driver->getWindowWidth(); - dmpy *= (float)Driver->getWindowHeight(); - } + dmpx *= (float)Driver->getWindowWidth(); + dmpy *= (float)Driver->getWindowHeight(); // handle inverted mouse, if enabled - if(ClientCfg.FreeLookInverted) dmpy = -dmpy; - + if (ClientCfg.FreeLookInverted) dmpy = -dmpy; + // update free look EventsListener.updateFreeLookPos(dmpx, dmpy); } // If the mouse move on the axis X, with a CGDMouseMove - if(EventsListener.isMouseAngleX()) - dx = -EventsListener.getMouseAngleX (); + if (EventsListener.isMouseAngleX()) + dx = -EventsListener.getMouseAngleX(); // If the mouse move on the axis Y, with a CGDMouseMove - if(EventsListener.isMouseAngleY()) - dy = EventsListener.getMouseAngleY (); + if (EventsListener.isMouseAngleY()) + dy = EventsListener.getMouseAngleY(); } @@ -1294,7 +1284,6 @@ void CUserControls::commonSetView() } } - //----------------------------------------------- // startFreeLook() //----------------------------------------------- diff --git a/code/ryzom/client/src/progress.cpp b/code/ryzom/client/src/progress.cpp index 0d5d4e4c9..8b5f72941 100644 --- a/code/ryzom/client/src/progress.cpp +++ b/code/ryzom/client/src/progress.cpp @@ -33,6 +33,7 @@ #include "client_cfg.h" #include "bg_downloader_access.h" #include "nel/misc/system_utils.h" +#include "nel/3d/stereo_hmd.h" using namespace std; using namespace NLMISC; @@ -173,186 +174,252 @@ void CProgress::internalProgress (float value) if (Driver->AsyncListener.isKeyPushed (KeyUP)) selectTipsOfTheDay (TipsOfTheDayIndex+1); - // Font factor - float fontFactor = 1; - if (Driver->getWindowHeight() > 0) - fontFactor = (float)Driver->getWindowHeight() / 600.f; - fontFactor *= _FontFactor; - // Set 2d view. - Driver->setMatrixMode2D11(); - Driver->clearBuffers (CRGBA(0,0,0,0)); - - // Display the loading background. - drawLoadingBitmap (value); - - // temporary values for conversions - float x, y, width, height; - - for(uint i = 0; i < ClientCfg.Logos.size(); i++) + // Create camera for stereo mode + bool stereoHMD = StereoHMD && !MainCam.empty() && (MainCam.getTransformMode() == UCamera::RotQuat); + CVector oldPos; + CQuat oldQuat; + if (stereoHMD) { - std::vector res; - explode(ClientCfg.Logos[i], std::string(":"), res); - if(res.size()==9 && idrawBitmap(x/(float)ClientCfg.Width, y/(float)ClientCfg.Height, width/(float)ClientCfg.Width, height/(float)ClientCfg.Height, *LogoBitmaps[i]); - } + MainCam.getPos(oldPos); + MainCam.getRotQuat(oldQuat); + StereoHMD->setInterfaceMatrix(CMatrix()); // identity + NLMISC::CQuat hmdOrient = StereoHMD->getOrientation(); + NLMISC::CMatrix camMatrix; + camMatrix.identity(); + NLMISC::CMatrix hmdMatrix; + hmdMatrix.setRot(hmdOrient); + NLMISC::CMatrix posMatrix; // minimal head modeling, will be changed in the future + posMatrix.translate(StereoHMD->getEyePosition()); + NLMISC::CMatrix mat = ((camMatrix * hmdMatrix) * posMatrix); + MainCam.setPos(mat.getPos()); + MainCam.setRotQuat(mat.getRot()); + StereoDisplay->updateCamera(0, &MainCam); } - - if (TextContext != NULL) + uint i = 0; + while ((!stereoHMD && i == 0) || (stereoHMD && StereoDisplay->nextPass())) { - // Init the Pen. - TextContext->setKeep800x600Ratio(false); - TextContext->setColor(CRGBA(255,255,255)); - TextContext->setFontSize((uint)(12.f * fontFactor)); - TextContext->setHotSpot(UTextContext::TopRight); + ++i; + if (stereoHMD) + { + // modify cameras for stereo display + const CViewport &vp = StereoDisplay->getCurrentViewport(); + Driver->setViewport(vp); + StereoDisplay->getCurrentMatrix(0, &MainCam); + StereoDisplay->getCurrentFrustum(0, &MainCam); + + // begin current pass + StereoDisplay->beginRenderTarget(); + + nldebug("Cam pos: %f, %f, %f", MainCam.getPos().x, MainCam.getPos().y, MainCam.getPos().z); + } + + if (!stereoHMD || StereoDisplay->wantClear()) + { + Driver->clearBuffers(CRGBA(0, 0, 0, 0)); + } + + if (stereoHMD && StereoDisplay->wantScene()) + { + Driver->setMatrixMode3D(MainCam); + } + + if (!stereoHMD || StereoDisplay->wantInterface2D()) + { + nldebug("Draw progress 2D"); + + // Font factor + float fontFactor = 1; + if (Driver->getWindowHeight() > 0) + fontFactor = (float)Driver->getWindowHeight() / 600.f; + fontFactor *= _FontFactor; + + // Set 2d view. + Driver->setMatrixMode2D11(); + + // Display the loading background. + drawLoadingBitmap(value); + + // temporary values for conversions + float x, y, width, height; + + for(uint i = 0; i < ClientCfg.Logos.size(); i++) + { + std::vector res; + explode(ClientCfg.Logos[i], std::string(":"), res); + if(res.size()==9 && idrawBitmap(x/(float)ClientCfg.Width, y/(float)ClientCfg.Height, width/(float)ClientCfg.Width, height/(float)ClientCfg.Height, *LogoBitmaps[i]); + } + } + + if (TextContext != NULL) + { + // Init the Pen. + TextContext->setKeep800x600Ratio(false); + TextContext->setColor(CRGBA(255,255,255)); + TextContext->setFontSize((uint)(12.f * fontFactor)); + TextContext->setHotSpot(UTextContext::TopRight); #if !FINAL_VERSION - // Display the Text. - TextContext->printAt(1, 0.98f, _ProgressMessage); + // Display the Text. + TextContext->printAt(1, 0.98f, _ProgressMessage); #else - if( ClientCfg.LoadingStringCount > 0 ) - { - TextContext->printAt(1, 0.98f, _ProgressMessage); - } + if( ClientCfg.LoadingStringCount > 0 ) + { + TextContext->printAt(1, 0.98f, _ProgressMessage); + } #endif // FINAL_VERSION - // Display the build version. - TextContext->setFontSize((uint)(12.f * fontFactor)); - TextContext->setHotSpot(UTextContext::TopRight); - string str; + // Display the build version. + TextContext->setFontSize((uint)(12.f * fontFactor)); + TextContext->setHotSpot(UTextContext::TopRight); + string str; #if FINAL_VERSION - str = "FV "; + str = "FV "; #else - str = "DEV "; + str = "DEV "; #endif - str += RYZOM_VERSION; - TextContext->printfAt(1.0f,1.0f, str.c_str()); + str += RYZOM_VERSION; + TextContext->printfAt(1.0f,1.0f, str.c_str()); - // Display the tips of the day. - TextContext->setFontSize((uint)(16.f * fontFactor)); - TextContext->setHotSpot(UTextContext::MiddleTop); - ucstring::size_type index = 0; - ucstring::size_type end = TipsOfTheDay.find((ucchar)'\n'); - if (end == string::npos) - end = TipsOfTheDay.size(); - float fY = ClientCfg.TipsY; - if (!TipsOfTheDay.empty()) - { - while (index < end) - { - // Get the line - ucstring line = TipsOfTheDay.substr (index, end-index); - - // Draw the line - TextContext->printAt(0.5f, fY, line); - fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY); - - index=end+1; - end = TipsOfTheDay.find((ucchar)'\n', index); - if (end == ucstring::npos) + // Display the tips of the day. + TextContext->setFontSize((uint)(16.f * fontFactor)); + TextContext->setHotSpot(UTextContext::MiddleTop); + ucstring::size_type index = 0; + ucstring::size_type end = TipsOfTheDay.find((ucchar)'\n'); + if (end == string::npos) end = TipsOfTheDay.size(); - } - - // More help - TextContext->setFontSize((uint)(12.f * fontFactor)); - /* todo tips of the day uncomment - ucstring ucstr = CI18N::get ("uiTipsEnd"); - TextContext->printAt(0.5f, fY, ucstr); */ - fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY); - fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY); - } - - - - if (!_TPReason.empty()) - { - TextContext->setHotSpot(UTextContext::MiddleMiddle); - TextContext->setFontSize((uint)(14.f * fontFactor)); - TextContext->printAt(0.5f, 0.5f, _TPReason); - TextContext->setHotSpot(UTextContext::BottomLeft); - TextContext->setColor(NLMISC::CRGBA::White); - } - - - - if (!_TPCancelText.empty()) - { - if (ClientCfg.Width != 0 && ClientCfg.Height != 0) - { - TextContext->setFontSize((uint)(15.f * fontFactor)); - TextContext->setHotSpot(UTextContext::BottomLeft); - - ucstring uc = CI18N::get("uiR2EDTPEscapeToInteruptLoading") + " (" + _TPCancelText + ") - " + CI18N::get("uiDelayedTPCancel"); - UTextContext::CStringInfo info = TextContext->getStringInfo(uc); - float stringX = 0.5f - info.StringWidth/(ClientCfg.Width*2); - TextContext->printAt(stringX, 7.f / ClientCfg.Height, uc); - } - } - - - // Teleport help - //fY = ClientCfg.TeleportInfoY; - if (!ApplyTextCommands && LoadingContinent && !LoadingContinent->Indoor) - { - TextContext->setFontSize((uint)(13.f * fontFactor)); - - // Print some more info - uint32 day = RT.getRyzomDay(); - str = toString (CI18N::get ("uiTipsTeleport").toUtf8().c_str(), - CI18N::get (LoadingContinent->LocalizedName).toUtf8().c_str(), - day, - (uint)RT.getRyzomTime(), - CI18N::get ("uiSeason"+toStringEnum(CRyzomTime::getSeasonByDay(day))).toUtf8().c_str(), - CI18N::get (WeatherManager.getCurrWeatherState().LocalizedName).toUtf8().c_str()); - ucstring ucstr; - ucstr.fromUtf8 (str); - TextContext->setHotSpot(UTextContext::MiddleBottom); - TextContext->setColor(CRGBA(186, 179, 163, 255)); - TextContext->printAt(0.5f, 25/768.f, ucstr); - } - - // apply text commands - if( ApplyTextCommands ) - { - std::vector printfCommands = ClientCfg.PrintfCommands; - if(FreeTrial) printfCommands = ClientCfg.PrintfCommandsFreeTrial; - - if( !printfCommands.empty() ) - { - TextContext->setHotSpot(UTextContext::MiddleBottom); - - vector::iterator itpc; - for( itpc = printfCommands.begin(); itpc != printfCommands.end(); ++itpc ) + float fY = ClientCfg.TipsY; + if (!TipsOfTheDay.empty()) { - float x = 0.5f;//((*itpc).X / 1024.f); - float y = ((*itpc).Y / 768.f); - TextContext->setColor( (*itpc).Color ); - TextContext->setFontSize( (uint)(16.f * fontFactor)); - - // build the ucstr(s) - ucstring ucstr = CI18N::get((*itpc).Text); - vector vucstr; - ucstring sep("\n"); - splitUCString(ucstr,sep,vucstr); - - // Letter size - UTextContext::CStringInfo si = TextContext->getStringInfo(ucstring("|")); - uint fontHeight = (uint) si.StringHeight + 2; // we add 2 pixels for the gap - - uint i; - float newy = y; - for( i=0; iprintAt(x,newy, vucstr[i]); - newy = nextLine(fontHeight, Driver->getWindowHeight(), newy); + // Get the line + ucstring line = TipsOfTheDay.substr (index, end-index); + + // Draw the line + TextContext->printAt(0.5f, fY, line); + fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY); + + index=end+1; + end = TipsOfTheDay.find((ucchar)'\n', index); + if (end == ucstring::npos) + end = TipsOfTheDay.size(); + } + + // More help + TextContext->setFontSize((uint)(12.f * fontFactor)); + /* todo tips of the day uncomment + ucstring ucstr = CI18N::get ("uiTipsEnd"); + TextContext->printAt(0.5f, fY, ucstr); */ + fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY); + fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY); + } + + + + if (!_TPReason.empty()) + { + TextContext->setHotSpot(UTextContext::MiddleMiddle); + TextContext->setFontSize((uint)(14.f * fontFactor)); + TextContext->printAt(0.5f, 0.5f, _TPReason); + TextContext->setHotSpot(UTextContext::BottomLeft); + TextContext->setColor(NLMISC::CRGBA::White); + } + + + + if (!_TPCancelText.empty()) + { + if (ClientCfg.Width != 0 && ClientCfg.Height != 0) + { + TextContext->setFontSize((uint)(15.f * fontFactor)); + TextContext->setHotSpot(UTextContext::BottomLeft); + + ucstring uc = CI18N::get("uiR2EDTPEscapeToInteruptLoading") + " (" + _TPCancelText + ") - " + CI18N::get("uiDelayedTPCancel"); + UTextContext::CStringInfo info = TextContext->getStringInfo(uc); + float stringX = 0.5f - info.StringWidth/(ClientCfg.Width*2); + TextContext->printAt(stringX, 7.f / ClientCfg.Height, uc); + } + } + + + // Teleport help + //fY = ClientCfg.TeleportInfoY; + if (!ApplyTextCommands && LoadingContinent && !LoadingContinent->Indoor) + { + TextContext->setFontSize((uint)(13.f * fontFactor)); + + // Print some more info + uint32 day = RT.getRyzomDay(); + str = toString (CI18N::get ("uiTipsTeleport").toUtf8().c_str(), + CI18N::get (LoadingContinent->LocalizedName).toUtf8().c_str(), + day, + (uint)RT.getRyzomTime(), + CI18N::get ("uiSeason"+toStringEnum(CRyzomTime::getSeasonByDay(day))).toUtf8().c_str(), + CI18N::get (WeatherManager.getCurrWeatherState().LocalizedName).toUtf8().c_str()); + ucstring ucstr; + ucstr.fromUtf8 (str); + TextContext->setHotSpot(UTextContext::MiddleBottom); + TextContext->setColor(CRGBA(186, 179, 163, 255)); + TextContext->printAt(0.5f, 25/768.f, ucstr); + } + + // apply text commands + if( ApplyTextCommands ) + { + std::vector printfCommands = ClientCfg.PrintfCommands; + if(FreeTrial) printfCommands = ClientCfg.PrintfCommandsFreeTrial; + + if( !printfCommands.empty() ) + { + TextContext->setHotSpot(UTextContext::MiddleBottom); + + vector::iterator itpc; + for( itpc = printfCommands.begin(); itpc != printfCommands.end(); ++itpc ) + { + float x = 0.5f;//((*itpc).X / 1024.f); + float y = ((*itpc).Y / 768.f); + TextContext->setColor( (*itpc).Color ); + TextContext->setFontSize( (uint)(16.f * fontFactor)); + + // build the ucstr(s) + ucstring ucstr = CI18N::get((*itpc).Text); + vector vucstr; + ucstring sep("\n"); + splitUCString(ucstr,sep,vucstr); + + // Letter size + UTextContext::CStringInfo si = TextContext->getStringInfo(ucstring("|")); + uint fontHeight = (uint) si.StringHeight + 2; // we add 2 pixels for the gap + + uint i; + float newy = y; + for( i=0; iprintAt(x,newy, vucstr[i]); + newy = nextLine(fontHeight, Driver->getWindowHeight(), newy); + } + } } } } } + + if (stereoHMD) + { + StereoDisplay->endRenderTarget(); + } + } /* stereo loop */ + + if (stereoHMD) + { + MainCam.setPos(oldPos); + MainCam.setRotQuat(oldQuat); } // Clamp diff --git a/code/ryzom/client/src/release.cpp b/code/ryzom/client/src/release.cpp index 722cbfe57..4e712a10d 100644 --- a/code/ryzom/client/src/release.cpp +++ b/code/ryzom/client/src/release.cpp @@ -120,7 +120,6 @@ extern bool userChar; extern bool serverReceivedReady; extern bool CharNameValidArrived; - extern void releaseContextualCursor(); extern void selectTipsOfTheDay (uint tips); @@ -498,7 +497,8 @@ void releaseOutGame() // Remove the Actions listener from the Events Server. EventsListener.removeFromServer(CInputHandlerManager::getInstance()->FilteredEventServer); - // Release Bloom + // Release effects + delete FXAA; FXAA = NULL; CBloomEffect::releaseInstance(); // Release Scene, textcontexts, materials, ... @@ -516,6 +516,16 @@ void releaseStereoDisplayDevice() { if (StereoDisplay) { + StereoDisplay->getOriginalFrustum(0, &MainCam); + if (SceneRoot) + { + UCamera cam = SceneRoot->getCam(); + StereoDisplay->getOriginalFrustum(1, &cam); + } + nlassert(Driver); + Driver->setViewport(NL3D::CViewport()); + nlassert(Scene); + Scene->setViewport(NL3D::CViewport()); delete StereoDisplay; StereoDisplay = NULL; StereoHMD = NULL; @@ -582,7 +592,8 @@ void release() Driver->deleteTextContext(TextContext); TextContext = NULL; - // Release Bloom + // Release effects + delete FXAA; FXAA = NULL; CBloomEffect::releaseInstance(); // Release Scene, textcontexts, materials, ... diff --git a/code/ryzom/client/src/stdpch.h b/code/ryzom/client/src/stdpch.h index 5f046fcfe..96a509e0f 100644 --- a/code/ryzom/client/src/stdpch.h +++ b/code/ryzom/client/src/stdpch.h @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include diff --git a/code/ryzom/client/src/user_entity.cpp b/code/ryzom/client/src/user_entity.cpp index c8652fd43..bb632cf4e 100644 --- a/code/ryzom/client/src/user_entity.cpp +++ b/code/ryzom/client/src/user_entity.cpp @@ -2384,10 +2384,13 @@ void CUserEntity::updateSound(const TTime &time) if (SoundMngr == 0) return; - SoundMngr->setListenerPos(pos()); - const CMatrix &camMat = MainCam.getMatrix(); - SoundMngr->setListenerOrientation(camMat.getJ(), camMat.getK()); - + if (!(StereoHMD && true)) // TODO: ClientCfg.Headphone + { + // NOTE: StereoHMD+Headphone impl in main_loop.cpp + SoundMngr->setListenerPos(pos()); + const CMatrix &camMat = MainCam.getMatrix(); + SoundMngr->setListenerOrientation(camMat.getJ(), camMat.getK()); + } if (ClientCfg.Light) return; diff --git a/code/snowballs2/client/src/camera.cpp b/code/snowballs2/client/src/camera.cpp index 9d9a5f777..0b7971192 100644 --- a/code/snowballs2/client/src/camera.cpp +++ b/code/snowballs2/client/src/camera.cpp @@ -128,6 +128,7 @@ void initCamera() StereoHMD->setScale(3.0f); // snowballs is about 4 units per meter } StereoDisplay->setDriver(Driver); // move after driver creation, move stereodisplay before driver creation + StereoDisplay->attachToDisplay(); } } } diff --git a/code/snowballs2/client/src/commands.cpp b/code/snowballs2/client/src/commands.cpp index 41faeab1e..d1929ab49 100644 --- a/code/snowballs2/client/src/commands.cpp +++ b/code/snowballs2/client/src/commands.cpp @@ -296,7 +296,7 @@ void initCommands() CommandsMaterial.setBlend(true); #if SBCLIENT_DEV_PIXEL_PROGRAM - CommandsMaterial.getObjectPtr()->setShader(NL3D::CMaterial::PostProcessing); + CommandsMaterial.getObjectPtr()->setShader(NL3D::CMaterial::Program); a_NelLogo = Driver->createTextureFile("nel128.tga"); CommandsMaterial.setTexture(dynamic_cast(a_NelLogo)); static const char *program_arbfp1 = @@ -340,7 +340,24 @@ void initCommands() "mov oC0.xzw, c0.xyyx\n" "texld oC0.y, v0, s0\n"; NL3D::IDriver *d = dynamic_cast(Driver)->getDriver(); - if (d->supportPixelProgram(CPixelProgram::fp40)) + a_DevPixelProgram = new CPixelProgram(); + // arbfp1 + { + IProgram::CSource *source = new IProgram::CSource(); + source->Features.MaterialFlags = CProgramFeatures::TextureStages; + source->Profile = IProgram::arbfp1; + source->setSourcePtr(program_arbfp1); + a_DevPixelProgram->addSource(source); + } + // ps_2_0 + { + IProgram::CSource *source = new IProgram::CSource(); + source->Features.MaterialFlags = CProgramFeatures::TextureStages; + source->Profile = IProgram::ps_2_0; + source->setSourcePtr(program_ps_2_0); + a_DevPixelProgram->addSource(source); + } + /*if (d->supportPixelProgram(CPixelProgram::fp40)) { nldebug("fp40"); a_DevPixelProgram = new CPixelProgram(program_fp40); @@ -349,14 +366,14 @@ void initCommands() { nldebug("arbfp1"); a_DevPixelProgram = new CPixelProgram(program_arbfp1); - } + }*/ /*else if (d->supportPixelProgram(CPixelProgram::ps_3_0)) { nldebug("ps_3_0"); a_DevPixelProgram = new CPixelProgram(program_ps_3_0); // Textures do not seem to work with ps_3_0... }*/ - else if (d->supportPixelProgram(CPixelProgram::ps_2_0)) + /*else if (d->supportPixelProgram(CPixelProgram::ps_2_0)) { nldebug("ps_2_0"); a_DevPixelProgram = new CPixelProgram(program_ps_2_0); @@ -365,7 +382,7 @@ void initCommands() { nldebug("ps_1_1"); a_DevPixelProgram = new CPixelProgram(program_ps_1_1); - } + }*/ #endif } @@ -385,17 +402,6 @@ void updateCommands() float CommandsBoxHeight = ((float)(sint32)((CommandsNbLines + 1) * CommandsLineHeight * width)) / width; float CommandsBoxBorderX = ((float)(sint32)(SBCLIENT::CommandsBoxBorder * width)) / width; float CommandsBoxBorderY = ((float)(sint32)(SBCLIENT::CommandsBoxBorder * height)) / height; - if (StereoHMD) - { - float xshift, yshift; - StereoHMD->getInterface2DShift(0, xshift, yshift, 4.f); - // snap to pixels - xshift = ((float)(sint32)(xshift * width)) / width; - yshift = ((float)(sint32)(yshift * height)) / height; - // adjust - CommandsBoxX += xshift; - CommandsBoxY += yshift; - } // Display the background Driver->setMatrixMode2D11 (); diff --git a/code/snowballs2/client/src/compass.cpp b/code/snowballs2/client/src/compass.cpp index 27e0e27f1..1c36d1f6b 100644 --- a/code/snowballs2/client/src/compass.cpp +++ b/code/snowballs2/client/src/compass.cpp @@ -95,13 +95,6 @@ void updateCompass () { float x = CompassPosX; float y = CompassPosY; - if (StereoHMD) - { - float xshift, yshift; - StereoHMD->getInterface2DShift(0, xshift, yshift, 4.f); - x += xshift; - y += yshift; - } float radius = CompassRadius; // tri @@ -117,8 +110,7 @@ void updateCompass () quad.V2.set ( radius, radius, 0); quad.V3.set (-radius, radius, 0); - if (StereoHMD) Driver->setMatrixMode2D11(); - else Driver->setMatrixMode2D43(); + Driver->setMatrixMode2D43(); CMatrix mtx; @@ -161,7 +153,7 @@ void updateCompass () Driver->setModelMatrix (mtx); Driver->drawQuad (quad, CompassMaterial); - if (!StereoHMD) x *= 3.0/4.0f; + x *= 3.0/4.0f; // Print position TextContext->setHotSpot(UTextContext::MiddleTop); diff --git a/code/snowballs2/client/src/snowballs_client.cpp b/code/snowballs2/client/src/snowballs_client.cpp index b401d80bc..68cdc47fa 100644 --- a/code/snowballs2/client/src/snowballs_client.cpp +++ b/code/snowballs2/client/src/snowballs_client.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #if SBCLIENT_DEV_STEREO # include #endif /* #if SBCLIENT_DEV_STEREO */ @@ -153,6 +154,7 @@ static IStereoRender *_StereoRender = NULL; #endif /* #if SBCLIENT_DEV_STEREO */ static bool s_EnableBloom = false; +static CFXAA *s_FXAA = NULL; // // Prototypes @@ -185,6 +187,7 @@ void cbGraphicsDriver(CConfigFile::CVar &var); void cbSquareBloom(CConfigFile::CVar &var); void cbDensityBloom(CConfigFile::CVar &var); void cbEnableBloom(CConfigFile::CVar &var); +void cbEnableFXAA(CConfigFile::CVar &var); // // Functions @@ -373,10 +376,11 @@ void initIngame() // initialize bloom effect CBloomEffect::instance().setDriver(Driver); CBloomEffect::instance().setScene(Scene); - CBloomEffect::instance().init(ConfigFile->getVar("OpenGL").asInt() == 1); + CBloomEffect::instance().init(); CConfiguration::setAndCallback("SquareBloom", cbSquareBloom); CConfiguration::setAndCallback("DensityBloom", cbDensityBloom); CConfiguration::setAndCallback("EnableBloom", cbEnableBloom); + CConfiguration::setAndCallback("EnableFXAA", cbEnableFXAA); // Init the landscape using the previously created UScene displayLoadingState("Initialize Landscape"); initLandscape(); @@ -740,7 +744,19 @@ void loopIngame() else { uint i = 0; - uint bloomStage = 0; + bool effectRender = false; + CTextureUser *effectRenderTarget = NULL; + bool haveEffects = Driver->getPolygonMode() == UDriver::Filled + && (s_EnableBloom || s_FXAA); + bool defaultRenderTarget = false; + if (haveEffects) + { + if (!StereoDisplay) + { + Driver->beginDefaultRenderTarget(); + defaultRenderTarget = true; + } + } while ((!StereoDisplay && i == 0) || (StereoDisplay && StereoDisplay->nextPass())) { ++i; @@ -762,13 +778,7 @@ void loopIngame() if (!StereoDisplay || StereoDisplay->wantClear()) { - - if (s_EnableBloom) - { - nlassert(bloomStage == 0); - CBloomEffect::instance().initBloom(); // start bloom effect (just before the first scene element render) - bloomStage = 1; - } + effectRender = haveEffects; // 01. Render Driver (background color) Driver->clearBuffers(CRGBA(0, 0, 127)); // clear all buffers, if you see this blue there's a problem with scene rendering @@ -788,13 +798,16 @@ void loopIngame() if (!StereoDisplay || StereoDisplay->wantInterface3D()) { - if (s_EnableBloom && bloomStage == 1) + if (effectRender) { - // End the actual bloom effect visible in the scene. if (StereoDisplay) Driver->setViewport(NL3D::CViewport()); - CBloomEffect::instance().endBloom(); + UCamera pCam = Scene->getCam(); + Driver->setMatrixMode2D11(); + if (s_FXAA) s_FXAA->applyEffect(); + if (s_EnableBloom) CBloomEffect::instance().applyBloom(); + Driver->setMatrixMode3D(pCam); if (StereoDisplay) Driver->setViewport(StereoDisplay->getCurrentViewport()); - bloomStage = 2; + effectRender = false; } // 06. Render Interface 3D (player names) @@ -803,15 +816,6 @@ void loopIngame() if (!StereoDisplay || StereoDisplay->wantInterface2D()) { - if (s_EnableBloom && bloomStage == 2) - { - // End bloom effect system after drawing the 3d interface (z buffer related). - if (StereoDisplay) Driver->setViewport(NL3D::CViewport()); - CBloomEffect::instance().endInterfacesDisplayBloom(); - if (StereoDisplay) Driver->setViewport(StereoDisplay->getCurrentViewport()); - bloomStage = 0; - } - // 07. Render Interface 2D (chatboxes etc, optionally does have 3d) updateCompass(); // Update the compass updateRadar(); // Update the radar @@ -833,6 +837,11 @@ void loopIngame() } // 09. Render Buffer + if (defaultRenderTarget) + { + // draw final result to backbuffer + Driver->endDefaultRenderTarget(Scene); + } Driver->swapBuffers(); } @@ -965,6 +974,22 @@ void cbEnableBloom(CConfigFile::CVar &var) s_EnableBloom = var.asBool(); } +void cbEnableFXAA(CConfigFile::CVar &var) +{ + bool enable = var.asBool(); + if (enable != (s_FXAA != NULL)) + { + if (enable) + { + s_FXAA = new CFXAA(Driver); + } + else + { + delete s_FXAA; + } + } +} + // // Loading state procedure // diff --git a/code/studio/src/plugins/object_viewer/graphics_viewport.h b/code/studio/src/plugins/object_viewer/graphics_viewport.h index 9bbad9806..a11081ffd 100644 --- a/code/studio/src/plugins/object_viewer/graphics_viewport.h +++ b/code/studio/src/plugins/object_viewer/graphics_viewport.h @@ -63,7 +63,6 @@ private Q_SLOTS: void setBackgroundColor(); void submitEvents(NLMISC::CEventServer &server, bool allWindows) { } - void emulateMouseRawMode(bool) { } void onResize( int width, int height );