Merge with multipass-stereo

This commit is contained in:
kaetemi 2013-09-14 00:46:56 +02:00
commit 387b4bc4cc
125 changed files with 14758 additions and 6902 deletions

View file

@ -52,6 +52,7 @@ FIND_LIBRARY(FREETYPE_LIBRARY_RELEASE
/opt/csw/lib
/opt/lib
/usr/freeware/lib64
/usr/lib/x86_64-linux-gnu
)
FIND_LIBRARY(FREETYPE_LIBRARY_DEBUG
@ -67,6 +68,7 @@ FIND_LIBRARY(FREETYPE_LIBRARY_DEBUG
/opt/csw/lib
/opt/lib
/usr/freeware/lib64
/usr/lib/x86_64-linux-gnu
)
IF(FREETYPE_INCLUDE_DIRS)

View file

@ -0,0 +1,70 @@
# - Locate LibOVR library
# This module defines
# LIBOVR_LIBRARIES, the libraries to link against
# LIBOVR_FOUND, if false, do not try to link to LIBOVR
# LIBOVR_INCLUDE_DIR, where to find headers.
IF(LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIR)
# in cache already
SET(LIBOVR_FIND_QUIETLY TRUE)
ENDIF(LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIR)
FIND_PATH(LIBOVR_INCLUDE_DIR
OVR.h
PATHS
$ENV{LIBOVR_DIR}/Include
/usr/local/include
/usr/include
/sw/include
/opt/local/include
/opt/csw/include
/opt/include
)
IF(UNIX)
IF(TARGET_X64)
SET(LIBOVR_LIBRARY_BUILD_PATH "Lib/Linux/Release/x86_64")
ELSE(TARGET_X64)
SET(LIBOVR_LIBRARY_BUILD_PATH "Lib/Linux/Release/i386")
ENDIF(TARGET_X64)
ELSEIF(APPLE)
SET(LIBOVR_LIBRARY_BUILD_PATH "Lib/MacOS/Release")
ELSEIF(WIN32)
IF(TARGET_X64)
SET(LIBOVR_LIBRARY_BUILD_PATH "Lib/x64")
ELSE(TARGET_X64)
SET(LIBOVR_LIBRARY_BUILD_PATH "Lib/Win32")
ENDIF(TARGET_X64)
ENDIF(UNIX)
FIND_LIBRARY(LIBOVR_LIBRARY
NAMES ovr
PATHS
$ENV{LIBOVR_DIR}/${LIBOVR_LIBRARY_BUILD_PATH}
/usr/local/lib
/usr/lib
/usr/local/X11R6/lib
/usr/X11R6/lib
/sw/lib
/opt/local/lib
/opt/csw/lib
/opt/lib
/usr/freeware/lib64
)
IF(LIBOVR_LIBRARY AND LIBOVR_INCLUDE_DIR)
IF(NOT LIBOVR_FIND_QUIETLY)
MESSAGE(STATUS "Found LibOVR: ${LIBOVR_LIBRARY}")
ENDIF(NOT LIBOVR_FIND_QUIETLY)
SET(LIBOVR_FOUND "YES")
SET(LIBOVR_DEFINITIONS "-DHAVE_LIBOVR")
IF(UNIX)
SET(LIBOVR_LIBRARIES ${LIBOVR_LIBRARY} X11 Xinerama udev pthread)
ELSE(UNIX)
SET(LIBOVR_LIBRARIES ${LIBOVR_LIBRARY})
ENDIF(UNIX)
ELSE(LIBOVR_LIBRARY AND LIBOVR_INCLUDE_DIR)
IF(NOT LIBOVR_FIND_QUIETLY)
MESSAGE(STATUS "Warning: Unable to find LibOVR!")
ENDIF(NOT LIBOVR_FIND_QUIETLY)
ENDIF(LIBOVR_LIBRARY AND LIBOVR_INCLUDE_DIR)

View file

@ -0,0 +1,32 @@
# - Locate LibVR library
# This module defines
# LIBVR_LIBRARIES, the libraries to link against
# LIBVR_FOUND, if false, do not try to link to LIBVR
# LIBVR_INCLUDE_DIR, where to find headers.
IF(LIBVR_LIBRARIES AND LIBVR_INCLUDE_DIR)
# in cache already
SET(LIBVR_FIND_QUIETLY TRUE)
ENDIF(LIBVR_LIBRARIES AND LIBVR_INCLUDE_DIR)
FIND_PATH(LIBVR_INCLUDE_DIR hmd.h
PATH_SUFFIXES include/LibVR
)
FIND_LIBRARY(LIBVR_LIBRARY
NAMES vr
PATH_SUFFIXES lib
PATHS
)
IF(LIBVR_LIBRARY AND LIBVR_INCLUDE_DIR)
IF(NOT LIBVR_FIND_QUIETLY)
MESSAGE(STATUS "Found LibVR: ${LIBVR_LIBRARY}")
ENDIF(NOT LIBVR_FIND_QUIETLY)
SET(LIBVR_FOUND "YES")
SET(LIBVR_DEFINITIONS "-DHAVE_LIBVR")
ELSE(LIBVR_LIBRARY AND LIBVR_INCLUDE_DIR)
IF(NOT LIBVR_FIND_QUIETLY)
MESSAGE(STATUS "Warning: Unable to find LibVR!")
ENDIF(NOT LIBVR_FIND_QUIETLY)
ENDIF(LIBVR_LIBRARY AND LIBVR_INCLUDE_DIR)

View file

@ -58,6 +58,8 @@ ELSE(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
SET(MYSQL_LIBRARIES optimized ${MYSQL_LIBRARY_RELEASE})
IF(MYSQL_LIBRARY_DEBUG)
SET(MYSQL_LIBRARIES ${MYSQL_LIBRARIES} debug ${MYSQL_LIBRARY_DEBUG})
ELSE(MYSQL_LIBRARY_DEBUG)
SET(MYSQL_LIBRARIES ${MYSQL_LIBRARIES} debug ${MYSQL_LIBRARY_RELEASE})
ENDIF(MYSQL_LIBRARY_DEBUG)
FIND_PACKAGE(OpenSSL)
IF(OPENSSL_FOUND)

View file

@ -320,6 +320,9 @@ MACRO(NL_SETUP_NEL_DEFAULT_OPTIONS)
OPTION(WITH_NEL_MAXPLUGIN "Build NeL 3dsMax Plugin" OFF)
OPTION(WITH_NEL_SAMPLES "Build NeL Samples" ON )
OPTION(WITH_NEL_TESTS "Build NeL Unit Tests" ON )
OPTION(WITH_LIBOVR "With LibOVR support" OFF)
OPTION(WITH_LIBVR "With LibVR support" OFF)
ENDMACRO(NL_SETUP_NEL_DEFAULT_OPTIONS)
MACRO(NL_SETUP_NELNS_DEFAULT_OPTIONS)

View file

@ -41,6 +41,14 @@ IF(WITH_GTK)
FIND_PACKAGE(GTK2)
ENDIF(WITH_GTK)
IF(WITH_LIBOVR)
FIND_PACKAGE(LibOVR)
ENDIF(WITH_LIBOVR)
IF(WITH_LIBVR)
FIND_PACKAGE(LibVR)
ENDIF(WITH_LIBVR)
IF(WITH_INSTALL_LIBRARIES)
IF(UNIX)
SET(prefix ${CMAKE_INSTALL_PREFIX})

View file

@ -138,6 +138,8 @@ private:
NLMISC::CSmartPtr<NL3D::ITexture> _BlurFinalTex;
// used as render target in first blur pass, and as displayed texture on second blur pass.
NLMISC::CSmartPtr<NL3D::ITexture> _BlurHorizontalTex;
// original render target
NLMISC::CSmartPtr<NL3D::ITexture> _OriginalRenderTarget;
// materials

File diff suppressed because it is too large Load diff

View file

@ -133,6 +133,7 @@ public:
// @{
virtual void disableHardwareVertexProgram();
virtual void disableHardwarePixelProgram();
virtual void disableHardwareVertexArrayAGP();
virtual void disableHardwareTextureShader();
@ -473,7 +474,6 @@ public:
virtual void forceDXTCCompression(bool dxtcComp);
virtual void setAnisotropicFilter(sint filter);
virtual void forceTextureResize(uint divisor);
virtual void forceNativeFragmentPrograms(bool nativeOnly);
virtual bool setMonitorColorProperties (const CMonitorColorProperties &properties);
// @}

View file

@ -0,0 +1,49 @@
/** \file geometry_program.h
* Geometry program definition
*/
/* Copyright, 2000, 2001 Nevrax Ltd.
*
* This file is part of NEVRAX NEL.
* NEVRAX NEL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
* NEVRAX NEL 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
* General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with NEVRAX NEL; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#ifndef NL_GEOMETRY_PROGRAM_H
#define NL_GEOMETRY_PROGRAM_H
#include <nel/misc/types_nl.h>
#include <nel/misc/smart_ptr.h>
#include <nel/3d/program.h>
#include <list>
namespace NL3D {
class CGeometryProgram : public IProgram
{
public:
/// Constructor
CGeometryProgram();
/// Destructor
virtual ~CGeometryProgram ();
};
} // NL3D
#endif // NL_GEOMETRY_PROGRAM_H
/* End of vertex_program.h */

View file

@ -0,0 +1,178 @@
/**
* \file gpu_program_params.h
* \brief CGPUProgramParams
* \date 2013-09-07 22:17GMT
* \author Jan Boon (Kaetemi)
* CGPUProgramParams
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef NL3D_GPU_PROGRAM_PARAMS_H
#define NL3D_GPU_PROGRAM_PARAMS_H
#include <nel/misc/types_nl.h>
// STL includes
#include <map>
#include <vector>
// NeL includes
// Project includes
namespace NLMISC {
class CVector;
class CMatrix;
}
namespace NL3D {
/**
* \brief CGPUProgramParams
* \date 2013-09-07 22:17GMT
* \author Jan Boon (Kaetemi)
* A storage for USERCODE-PROVIDED parameters for GPU programs.
* Allows for fast updating and iteration of parameters.
* NOTE TO DRIVER IMPLEMENTORS: DO NOT USE FOR STORING COPIES
* OF HARDCODED DRIVER MATERIAL PARAMETERS OR DRIVER PARAMETERS!!!
* The 4-component alignment that is done in this storage
* class is necessary to simplify support for register-based
* assembly shaders, which require setting per 4 components.
*/
class CGPUProgramParams
{
public:
enum TType { Float, Int, UInt };
struct CMeta { uint Index, Size, Count; TType Type; std::string Name; size_t Next, Prev; }; // size is element size, count is nb of elements
private:
union CVec { float F[4]; sint32 I[4]; uint32 UI[4]; };
public:
CGPUProgramParams();
virtual ~CGPUProgramParams();
/// \name User functions
// @{
// Copy from another params storage
void copy(CGPUProgramParams *params);
// Set by index, available only when the associated program has been compiled
void set1f(uint index, float f0);
void set2f(uint index, float f0, float f1);
void set3f(uint index, float f0, float f1, float f2);
void set4f(uint index, float f0, float f1, float f2, float f3);
void set1i(uint index, sint32 i0);
void set2i(uint index, sint32 i0, sint32 i1);
void set3i(uint index, sint32 i0, sint32 i1, sint32 i2);
void set4i(uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3);
void set1ui(uint index, uint32 ui0);
void set2ui(uint index, uint32 ui0, uint32 ui1);
void set3ui(uint index, uint32 ui0, uint32 ui1, uint32 ui2);
void set4ui(uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3);
void set3f(uint index, const NLMISC::CVector& v);
void set4f(uint index, const NLMISC::CVector& v, float f3);
void set4x4f(uint index, const NLMISC::CMatrix& m);
void set4fv(uint index, size_t num, const float *src);
void set4iv(uint index, size_t num, const sint32 *src);
void set4uiv(uint index, size_t num, const uint32 *src);
void unset(uint index);
// Set by name, it is recommended to use index when repeatedly setting an element
void set1f(const std::string &name, float f0);
void set2f(const std::string &name, float f0, float f1);
void set3f(const std::string &name, float f0, float f1, float f2);
void set4f(const std::string &name, float f0, float f1, float f2, float f3);
void set1i(const std::string &name, sint32 i0);
void set2i(const std::string &name, sint32 i0, sint32 i1);
void set3i(const std::string &name, sint32 i0, sint32 i1, sint32 i2);
void set4i(const std::string &name, sint32 i0, sint32 i1, sint32 i2, sint32 i3);
void set1ui(const std::string &name, uint32 ui0);
void set2ui(const std::string &name, uint32 ui0, uint32 ui1);
void set3ui(const std::string &name, uint32 ui0, uint32 ui1, uint32 ui2);
void set4ui(const std::string &name, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3);
void set3f(const std::string &name, const NLMISC::CVector& v);
void set4f(const std::string &name, const NLMISC::CVector& v, float f3);
void set4x4f(const std::string &name, const NLMISC::CMatrix& m);
void set4fv(const std::string &name, size_t num, const float *src);
void set4iv(const std::string &name, size_t num, const sint32 *src);
void set4uiv(const std::string &name, size_t num, const uint32 *src);
void unset(const std::string &name);
// @}
// Maps the given name to the given index.
// on duplicate entry the data set by name will be prefered, as it can be
// assumed to have been set after the data set by index, and the mapping
// will usually happen while iterating and finding an element with name
// but no known index.
// Unknown index will be set to ~0, unknown name will have an empty string.
void map(uint index, const std::string &name);
/// \name Internal
// @{
/// Allocate specified number of components if necessary (internal use only)
size_t allocOffset(uint index, uint size, uint count, TType type);
size_t allocOffset(const std::string &name, uint size, uint count, TType type);
size_t allocOffset(uint size, uint count, TType type);
/// Return offset for specified index
size_t getOffset(uint index) const;
size_t getOffset(const std::string &name) const;
/// Remove by offset
void freeOffset(size_t offset);
// @}
/// \name Driver and dev tools
// @{
// Iteration (returns the offsets for access using getFooByOffset)
inline size_t getBegin() const { return m_Meta.size() ? m_First : s_End; }
inline size_t getNext(size_t offset) const { return m_Meta[offset].Next; }
inline size_t getEnd() const { return s_End; }
// Data access
inline uint getSizeByOffset(size_t offset) const { return m_Meta[offset].Size; } // size of element (4 for float4)
inline uint getCountByOffset(size_t offset) const { return m_Meta[offset].Count; } // number of elements (usually 1)
inline uint getNbComponentsByOffset(size_t offset) const { return m_Meta[offset].Size * m_Meta[offset].Count; } // nb of components (size * count)
inline float *getPtrFByOffset(size_t offset) { return m_Vec[offset].F; }
inline sint32 *getPtrIByOffset(size_t offset) { return m_Vec[offset].I; }
inline uint32 *getPtrUIByOffset(size_t offset) { return m_Vec[offset].UI; }
inline TType getTypeByOffset(size_t offset) const { return m_Meta[offset].Type; }
inline uint getIndexByOffset(size_t offset) const { return m_Meta[offset].Index; }
const std::string &getNameByOffset(size_t offset) const { return m_Meta[offset].Name; };
// @}
// Utility
static inline uint getNbRegistersByComponents(uint nbComponents) { return (nbComponents + 3) >> 2; } // vector register per 4 components
private:
std::vector<CVec> m_Vec;
std::vector<CMeta> m_Meta;
std::vector<size_t> m_Map; // map from index to offset
std::map<std::string, size_t> m_MapName; // map from name to offset
size_t m_First;
size_t m_Last;
static const size_t s_End = -1;
}; /* class CGPUProgramParams */
} /* namespace NL3D */
#endif /* #ifndef NL3D_GPU_PROGRAM_PARAMS_H */
/* end of file */

View file

@ -21,6 +21,7 @@
#include "nel/misc/smart_ptr.h"
#include "nel/3d/tessellation.h"
#include "nel/3d/vertex_buffer.h"
#include "nel/3d/vertex_program.h"
namespace NL3D
@ -41,6 +42,7 @@ class CVertexProgram;
#define NL3D_LANDSCAPE_VPPOS_DELTAPOS (CVertexBuffer::TexCoord3)
#define NL3D_LANDSCAPE_VPPOS_ALPHAINFO (CVertexBuffer::TexCoord4)
class CVertexProgramLandscape;
// ***************************************************************************
/**
@ -107,6 +109,8 @@ public:
* Give a vertexProgram Id to activate. Always 0, but 1 For tile Lightmap Pass.
*/
void activate(uint vpId);
void activateVP(uint vpId);
inline CVertexProgramLandscape *getVP(uint vpId) const { return _VertexProgram[vpId]; }
// @}
@ -151,15 +155,35 @@ private:
/// \name Vertex Program mgt .
// @{
public:
enum {MaxVertexProgram= 2,};
// Vertex Program , NULL if not enabled.
CVertexProgram *_VertexProgram[MaxVertexProgram];
private:
NLMISC::CSmartPtr<CVertexProgramLandscape> _VertexProgram[MaxVertexProgram];
void deleteVertexProgram();
void setupVBFormatAndVertexProgram(bool withVertexProgram);
// @}
};
class CVertexProgramLandscape : public CVertexProgram
{
public:
struct CIdx
{
uint ProgramConstants0;
uint RefineCenter;
uint TileDist;
uint PZBModelPosition;
};
CVertexProgramLandscape(CLandscapeVBAllocator::TType type, bool lightMap = false);
virtual ~CVertexProgramLandscape() { }
virtual void buildInfo();
public:
const CIdx &idx() const { return m_Idx; }
CIdx m_Idx;
};
} // NL3D

View file

@ -22,7 +22,6 @@
#include "nel/misc/rgba.h"
#include "nel/misc/matrix.h"
#include "nel/3d/texture.h"
#include "nel/3d/shader.h"
#include <memory>
@ -171,7 +170,8 @@ public:
* - Alpha of texture in stage 0 is blended with alpha of texture in stage 1. Blend done with the alpha color of each
* stage and the whole is multiplied by the alpha in color vertex [AT0*ADiffuseCol+AT1*(1-ADiffuseCol)]*AStage
* - RGB still unchanged
*
* Water :
* - Water
*/
enum TShader { Normal=0,
Bump,
@ -183,7 +183,8 @@ public:
PerPixelLightingNoSpec,
Cloud,
Water,
shaderCount};
shaderCount,
Program /* internally used when a pixel program is active */ };
/// \name Texture Env Modes.
// @{

View file

@ -27,6 +27,7 @@
namespace NL3D {
class CVertexProgramPerPixelLight;
/**
* This vertex program is used to perform perpixel lighting with meshs. Its outputs are :
@ -49,6 +50,8 @@ namespace NL3D {
class CMeshVPPerPixelLight : public IMeshVertexProgram
{
public:
friend class CVertexProgramPerPixelLight;
/// true if want Specular Lighting.
bool SpecularLighting;
public:
@ -84,7 +87,9 @@ private:
bool _IsPointLight;
//
enum { NumVp = 8};
static std::auto_ptr<CVertexProgram> _VertexProgram[NumVp];
static NLMISC::CSmartPtr<CVertexProgramPerPixelLight> _VertexProgram[NumVp];
NLMISC::CRefPtr<CVertexProgramPerPixelLight> _ActiveVertexProgram;
};
} // NL3D

View file

@ -24,6 +24,7 @@
namespace NL3D {
class CVertexProgramWindTree;
// ***************************************************************************
/**
@ -35,6 +36,7 @@ namespace NL3D {
class CMeshVPWindTree : public IMeshVertexProgram
{
public:
friend class CVertexProgramWindTree;
enum {HrcDepth= 3};
@ -112,7 +114,9 @@ private:
/** The 16 versions: Specular or not (0 or 2), + normalize normal or not (0 or 1).
* All multiplied by 4, because support from 0 to 3 pointLights activated. (0.., 4.., 8.., 12..)
*/
static std::auto_ptr<CVertexProgram> _VertexProgram[NumVp];
static NLMISC::CSmartPtr<CVertexProgramWindTree> _VertexProgram[NumVp];
NLMISC::CRefPtr<CVertexProgramWindTree> _ActiveVertexProgram;
// WindTree Time for this mesh param setup. Stored in mesh because same for all instances.
float _CurrentTime[HrcDepth];

View file

@ -0,0 +1,49 @@
/** \file pixel_program.h
* Pixel program definition
*/
/* Copyright, 2000, 2001 Nevrax Ltd.
*
* This file is part of NEVRAX NEL.
* NEVRAX NEL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
* NEVRAX NEL 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
* General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with NEVRAX NEL; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#ifndef NL_PIXEL_PROGRAM_H
#define NL_PIXEL_PROGRAM_H
#include <nel/misc/types_nl.h>
#include <nel/misc/smart_ptr.h>
#include <nel/3d/program.h>
#include <list>
namespace NL3D {
class CPixelProgram : public IProgram
{
public:
/// Constructor
CPixelProgram();
/// Destructor
virtual ~CPixelProgram ();
};
} // NL3D
#endif // NL_PIXEL_PROGRAM_H
/* End of vertex_program.h */

View file

@ -0,0 +1,264 @@
/**
* \file program.h
* \brief IProgram
* \date 2013-09-07 15:00GMT
* \author Jan Boon (Kaetemi)
* IProgram
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef NL3D_PROGRAM_H
#define NL3D_PROGRAM_H
#include <nel/misc/types_nl.h>
// STL includes
// NeL includes
#include <nel/misc/smart_ptr.h>
// Project includes
namespace NL3D {
// List typedef.
class IDriver;
class IProgramDrvInfos;
typedef std::list<IProgramDrvInfos*> TGPUPrgDrvInfoPtrList;
typedef TGPUPrgDrvInfoPtrList::iterator ItGPUPrgDrvInfoPtrList;
// Class for interaction of vertex program with Driver.
// IProgramDrvInfos represent the real data of the GPU program, stored into the driver (eg: just a GLint for opengl).
class IProgramDrvInfos : public NLMISC::CRefCount
{
private:
IDriver *_Driver;
ItGPUPrgDrvInfoPtrList _DriverIterator;
public:
IProgramDrvInfos (IDriver *drv, ItGPUPrgDrvInfoPtrList it);
// The virtual dtor is important.
virtual ~IProgramDrvInfos(void);
virtual uint getUniformIndex(const char *name) const = 0;
};
// Features exposed by a program. Used to set builtin parameters on user provided shaders.
// This is only used for user provided shaders, not for builtin shaders,
// as it is a slow method which has to go through all of the options every time.
// Builtin shaders should set all flags to 0.
// Example:
// User shader flags Matrices in the Vertex Program:
// -> When rendering with a material, the driver will call setUniformDriver,
// which will check if the flag Matrices exists, and if so, it will use
// the index cache to find which matrices are needed by the shader,
// and set those which are found.
// This does not work extremely efficient, but it's the most practical option
// for passing builtin parameters onto user provided shaders.
// Note: May need additional flags related to scene sorting, etcetera.
struct CProgramFeatures
{
CProgramFeatures() : DriverFlags(0), MaterialFlags(0) { }
// Driver builtin parameters
enum TDriverFlags
{
// Matrices
Matrices = 0x00000001,
// Fog
Fog = 0x00000002,
};
uint32 DriverFlags;
enum TMaterialFlags
{
/// Use the CMaterial texture stages as the textures for a Pixel Program
TextureStages = 0x00000001,
TextureMatrices = 0x00000002,
};
// Material builtin parameters
uint32 MaterialFlags;
};
// Stucture used to cache the indices of builtin parameters which are used by the drivers
// Not used for parameters of specific nl3d programs
struct CProgramIndex
{
enum TName
{
ModelView,
ModelViewInverse,
ModelViewTranspose,
ModelViewInverseTranspose,
Projection,
ProjectionInverse,
ProjectionTranspose,
ProjectionInverseTranspose,
ModelViewProjection,
ModelViewProjectionInverse,
ModelViewProjectionTranspose,
ModelViewProjectionInverseTranspose,
Fog,
NUM_UNIFORMS
};
static const char *Names[NUM_UNIFORMS];
uint Indices[NUM_UNIFORMS];
};
/**
* \brief IProgram
* \date 2013-09-07 15:00GMT
* \author Jan Boon (Kaetemi)
* A generic GPU program
*/
class IProgram : public NLMISC::CRefCount
{
public:
enum TProfile
{
none = 0,
// types
// Vertex Shader = 0x01
// Pixel Shader = 0x02
// Geometry Shader = 0x03
// nel - 0x31,type,bitfield
nelvp = 0x31010001, // VP supported by CVertexProgramParser, similar to arbvp1, can be translated to vs_1_1
// direct3d - 0xD9,type,major,minor
// vertex programs
vs_1_1 = 0xD9010101,
vs_2_0 = 0xD9010200,
// vs_2_sw = 0xD9010201, // not sure...
// vs_2_x = 0xD9010202, // not sure...
// vs_3_0 = 0xD9010300, // not supported
// pixel programs
ps_1_1 = 0xD9020101,
ps_1_2 = 0xD9020102,
ps_1_3 = 0xD9020103,
ps_1_4 = 0xD9020104,
ps_2_0 = 0xD9020200,
// ps_2_x = 0xD9020201, // not sure...
// ps_3_0 = 0xD9020300, // not supported
// opengl - 0x61,type,bitfield
// vertex programs
// vp20 = 0x61010001, // NV_vertex_program1_1, outdated
arbvp1 = 0x61010002, // ARB_vertex_program
vp30 = 0x61010004, // NV_vertex_program2
vp40 = 0x61010008, // NV_vertex_program3 + NV_fragment_program3
gp4vp = 0x61010010, // NV_gpu_program4
gp5vp = 0x61010020, // NV_gpu_program5
// pixel programs
// fp20 = 0x61020001, // very limited and outdated, unnecessary
// fp30 = 0x61020002, // NV_fragment_program, now arbfp1, redundant
arbfp1 = 0x61020004, // ARB_fragment_program
fp40 = 0x61020008, // NV_fragment_program2, arbfp1 with "OPTION NV_fragment_program2;\n"
gp4fp = 0x61020010, // NV_gpu_program4
gp5fp = 0x61020020, // NV_gpu_program5
// geometry programs
gp4gp = 0x61030001, // NV_gpu_program4
gp5gp = 0x61030001, // NV_gpu_program5
// glsl - 0x65,type,version
glsl330v = 0x65010330, // GLSL vertex program version 330
glsl330f = 0x65020330, // GLSL fragment program version 330
glsl330g = 0x65030330, // GLSL geometry program version 330
};
struct CSource : public NLMISC::CRefCount
{
public:
std::string DisplayName;
/// Minimal required profile for this GPU program
IProgram::TProfile Profile;
const char *SourcePtr;
size_t SourceLen;
/// Copy the source code string
inline void setSource(const std::string &source) { SourceCopy = source; SourcePtr = &SourceCopy[0]; SourceLen = SourceCopy.size(); }
inline void setSource(const char *source) { SourceCopy = source; SourcePtr = &SourceCopy[0]; SourceLen = SourceCopy.size(); }
/// Set pointer to source code string without copying the string
inline void setSourcePtr(const char *sourcePtr, size_t sourceLen) { SourceCopy.clear(); SourcePtr = sourcePtr; SourceLen = sourceLen; }
inline void setSourcePtr(const char *sourcePtr) { SourceCopy.clear(); SourcePtr = sourcePtr; SourceLen = strlen(sourcePtr); }
/// CVertexProgramInfo/CPixelProgramInfo/... NeL features
CProgramFeatures Features;
/// Map with known parameter indices, used for assembly programs
std::map<std::string, uint> ParamIndices;
private:
std::string SourceCopy;
};
public:
IProgram();
virtual ~IProgram();
// Manage the sources, not allowed after compilation.
// Add multiple sources using different profiles, the driver will use the first one it supports.
inline size_t getSourceNb() const { return m_Sources.size(); };
inline CSource *getSource(size_t i) const { return m_Sources[i]; };
inline size_t addSource(CSource *source) { nlassert(!m_Source); m_Sources.push_back(source); return (m_Sources.size() - 1); }
inline void removeSource(size_t i) { nlassert(!m_Source); m_Sources.erase(m_Sources.begin() + i); }
// Get the idx of a parameter (ogl: uniform, d3d: constant, etcetera) by name. Invalid name returns ~0
inline uint getUniformIndex(const char *name) const { return m_DrvInfo->getUniformIndex(name); };
inline uint getUniformIndex(const std::string &name) const { return m_DrvInfo->getUniformIndex(name.c_str()); };
inline uint getUniformIndex(CProgramIndex::TName name) const { return m_Index.Indices[name]; }
// Get feature information of the current program
inline CSource *source() const { return m_Source; };
inline const CProgramFeatures &features() const { return m_Source->Features; };
inline TProfile profile() const { return m_Source->Profile; }
// Build feature info, called automatically by the driver after compile succeeds
void buildInfo(CSource *source);
// Override this to build additional info in a subclass
virtual void buildInfo();
protected:
/// The progam source
std::vector<NLMISC::CSmartPtr<CSource> > m_Sources;
/// The source used for compilation
NLMISC::CSmartPtr<CSource> m_Source;
CProgramIndex m_Index;
public:
/// The driver information. For the driver implementation only.
NLMISC::CRefPtr<IProgramDrvInfos> m_DrvInfo;
}; /* class IProgram */
} /* namespace NL3D */
#endif /* #ifndef NL3D_PROGRAM_H */
/* end of file */

View file

@ -27,6 +27,7 @@
#include "nel/3d/mesh_block_manager.h"
#include "nel/3d/shadow_map_manager.h"
#include "nel/3d/u_scene.h"
#include "nel/3d/vertex_program.h"
#include <vector>
@ -68,6 +69,41 @@ class CWaterModel;
#define NL3D_SHADOW_MESH_SKIN_MANAGER_MAXVERTICES 3000
#define NL3D_SHADOW_MESH_SKIN_MANAGER_NUMVB 8
/// Container for lighted vertex program.
class CVertexProgramLighted : public CVertexProgram
{
public:
static const uint MaxLight = 4;
static const uint MaxPointLight = (MaxLight - 1);
struct CIdxLighted
{
uint Ambient;
uint Diffuse[MaxLight];
uint Specular[MaxLight];
uint DirOrPos[MaxLight]; // light 0, directional sun; light 1,2,3, omni point light
uint EyePosition;
uint DiffuseAlpha;
};
struct CFeaturesLighted
{
/// Number of point lights that this program is generated for, varies from 0 to 3.
uint NumActivePointLights;
bool SupportSpecular;
bool Normalize;
/// Start of constants to use for lighting with assembly shaders.
uint CtStartNeLVP;
};
CVertexProgramLighted() { }
virtual ~CVertexProgramLighted() { }
virtual void buildInfo();
const CIdxLighted &idxLighted() const { return m_IdxLighted; }
const CFeaturesLighted &featuresLighted() const { return m_FeaturesLighted; }
protected:
CIdxLighted m_IdxLighted;
CFeaturesLighted m_FeaturesLighted;
};
// ***************************************************************************
@ -224,7 +260,7 @@ public:
// @{
// Max VP Light setup Infos.
enum {MaxVPLight= 4};
enum {MaxVPLight = CVertexProgramLighted::MaxLight};
/** reset the lighting setup in the driver (all lights are disabled).
* called at beginning of traverse(). Must be called by any model (before and after rendering)
@ -253,7 +289,7 @@ public:
* \param supportSpecular asitsounds. PointLights and dirLight are localViewer
* \param invObjectWM the inverse of object matrix: lights are mul by this. Vp compute in object space.
*/
void beginVPLightSetup(uint ctStart, bool supportSpecular, const CMatrix &invObjectWM);
void beginVPLightSetup(CVertexProgramLighted *program, const CMatrix &invObjectWM);
/** change the driver VP LightSetup constants which depends on material.
* \param excludeStrongest This remove the strongest light from the setup. The typical use is to have it computed by using perpixel lighting.
@ -299,7 +335,8 @@ public:
* \param numActivePoinLights tells how many point light from 0 to 3 this VP must handle. NB: the Sun directionnal is not option
* NB: nlassert(numActiveLights<=MaxVPLight-1).
*/
static std::string getLightVPFragment(uint numActivePointLights, uint ctStart, bool supportSpecular, bool normalize);
static std::string getLightVPFragmentNeLVP(uint numActivePointLights, uint ctStart, bool supportSpecular, bool normalize);
// TODO_VP_GLSL
/** This returns a reference to a driver light, by its index
* \see getStrongestLightIndex
@ -381,12 +418,14 @@ private:
mutable uint _StrongestLightIndex;
mutable bool _StrongestLightTouched;
// Current vp setuped with beginVPLightSetup()
NLMISC::CRefPtr<CVertexProgramLighted> _VPCurrent;
// Current ctStart setuped with beginVPLightSetup()
uint _VPCurrentCtStart;
//uint _VPCurrentCtStart;
// Current num of VP lights enabled.
uint _VPNumLights;
// Current support of specular
bool _VPSupportSpecular;
//bool _VPSupportSpecular;
// Sum of all ambiant of all lights + ambiantGlobal.
NLMISC::CRGBAF _VPFinalAmbient;
// Diffuse/Spec comp of all light / 255.

View file

@ -826,7 +826,8 @@ private:
void flushSSSModelRequests();
// common vb for water display
CVertexBuffer _WaterVB;
bool _RequestParticlesAnimate;
};

View file

@ -1,99 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// 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 <http://www.gnu.org/licenses/>.
#ifndef NL_SHADER_H
#define NL_SHADER_H
#include "nel/misc/types_nl.h"
#include "nel/misc/smart_ptr.h"
#include <list>
namespace NL3D {
using NLMISC::CRefCount;
class IDriver;
// List typedef.
class IShaderDrvInfos;
typedef std::list<IShaderDrvInfos*> TShaderDrvInfoPtrList;
typedef TShaderDrvInfoPtrList::iterator ItShaderDrvInfoPtrList;
/**
* Interface for shader driver infos.
*/
class IShaderDrvInfos : public CRefCount
{
private:
IDriver *_Driver;
ItShaderDrvInfoPtrList _DriverIterator;
public:
IShaderDrvInfos(IDriver *drv, ItShaderDrvInfoPtrList it) {_Driver= drv; _DriverIterator= it;}
// The virtual dtor is important.
virtual ~IShaderDrvInfos();
};
/**
* Shader resource for the driver. It is just a container for a ".fx" text file.
*/
/* *** IMPORTANT ********************
* *** IF YOU MODIFY THE STRUCTURE OF THIS CLASS, PLEASE INCREMENT IDriver::InterfaceVersion TO INVALIDATE OLD DRIVER DLL
* **********************************
*/
// --------------------------------------------------
class CShader
{
public:
CShader();
~CShader();
// Load a shader file
bool loadShaderFile (const char *filename);
// Set the shader text
void setText (const char *text);
// Get the shader text
const char *getText () const { return _Text.c_str(); }
// Set the shader name
void setName (const char *name);
// Get the shader name
const char *getName () const { return _Name.c_str(); }
public:
// Private. For Driver only.
bool _ShaderChanged;
NLMISC::CRefPtr<IShaderDrvInfos> _DrvInfo;
private:
// The shader
std::string _Text;
// The shader name
std::string _Name;
};
} // NL3D
#endif // NL_SHADER_H
/* End of shader.h */

View file

@ -0,0 +1,134 @@
/**
* \file stereo_debugger.h
* \brief CStereoDebugger
* \date 2013-07-03 20:17GMT
* \author Jan Boon (Kaetemi)
* CStereoDebugger
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#if !FINAL_VERSION
#ifndef NL3D_STEREO_DEBUGGER_H
#define NL3D_STEREO_DEBUGGER_H
#include <nel/misc/types_nl.h>
// STL includes
// NeL includes
#include <nel/misc/smart_ptr.h>
#include <nel/misc/geom_ext.h>
// Project includes
#include <nel/3d/stereo_display.h>
#include <nel/3d/frustum.h>
#include <nel/3d/viewport.h>
#include <nel/3d/u_material.h>
#define NL_STEREO_MAX_USER_CAMERAS 8
namespace NL3D {
class ITexture;
class CTextureUser;
class CPixelProgram;
/**
* \brief CStereoDebugger
* \date 2013-07-03 20:17GMT
* \author Jan Boon (Kaetemi)
* CStereoDebugger
*/
class CStereoDebugger : public IStereoDisplay
{
public:
CStereoDebugger();
virtual ~CStereoDebugger();
/// Sets driver and generates necessary render targets
virtual void setDriver(NL3D::UDriver *driver);
void releaseTextures();
void initTextures();
void setTextures();
void verifyTextures();
/// 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;
/// 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();
/// Interface within the 3D scene
virtual bool wantInterface3D();
/// 2D Interface
virtual bool wantInterface2D();
/// 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();
static void listDevices(std::vector<CStereoDeviceInfo> &devicesOut);
private:
UDriver *m_Driver;
int m_Stage;
int m_SubStage;
CViewport m_LeftViewport;
CViewport m_RightViewport;
CFrustum m_Frustum[NL_STEREO_MAX_USER_CAMERAS];
CMatrix m_CameraMatrix[NL_STEREO_MAX_USER_CAMERAS];
NLMISC::CSmartPtr<NL3D::ITexture> m_LeftTex;
NL3D::CTextureUser *m_LeftTexU;
NLMISC::CSmartPtr<NL3D::ITexture> m_RightTex;
NL3D::CTextureUser *m_RightTexU;
NL3D::UMaterial m_Mat;
NLMISC::CQuadUV m_QuadUV;
CPixelProgram *m_PixelProgram;
}; /* class CStereoDebugger */
} /* namespace NL3D */
#endif /* #ifndef NL3D_STEREO_DEBUGGER_H */
#endif /* #if !FINAL_VERSION */
/* end of file */

View file

@ -0,0 +1,141 @@
/**
* \file stereo_display.h
* \brief IStereoDisplay
* \date 2013-06-27 16:29GMT
* \author Jan Boon (Kaetemi)
* IStereoDisplay
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef NL3D_STEREO_DISPLAY_H
#define NL3D_STEREO_DISPLAY_H
#include <nel/misc/types_nl.h>
// STL includes
// NeL includes
#include <nel/misc/smart_ptr.h>
// Project includes
namespace NL3D {
class UCamera;
class CViewport;
class CFrustum;
class IStereoDisplay;
class UTexture;
class UDriver;
class IStereoDeviceFactory : public NLMISC::CRefCount
{
public:
IStereoDeviceFactory() { }
virtual ~IStereoDeviceFactory() { }
virtual IStereoDisplay *createDevice() const = 0;
};
struct CStereoDeviceInfo
{
public:
enum TStereoDeviceClass
{
StereoDisplay,
StereoHMD,
};
enum TStereoDeviceLibrary
{
NeL3D,
OVR,
LibVR,
OpenHMD,
};
NLMISC::CSmartPtr<IStereoDeviceFactory> Factory;
TStereoDeviceLibrary Library;
TStereoDeviceClass Class;
std::string Manufacturer;
std::string ProductName;
std::string Serial; // A unique device identifier
};
/**
* \brief IStereoDisplay
* \date 2013-06-27 16:29GMT
* \author Jan Boon (Kaetemi)
* IStereoDisplay
*/
class IStereoDisplay
{
public:
IStereoDisplay();
virtual ~IStereoDisplay();
/// Sets driver and generates necessary render targets
virtual void setDriver(NL3D::UDriver *driver) = 0;
/// Gets the required screen resolution for this device
virtual bool getScreenResolution(uint &width, uint &height) = 0;
/// Set latest camera position etcetera
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;
/// Is there a next pass
virtual bool nextPass() = 0;
/// Gets the current viewport
virtual const NL3D::CViewport &getCurrentViewport() const = 0;
/// Gets the current camera frustum
virtual const NL3D::CFrustum &getCurrentFrustum(uint cid) const = 0;
/// Gets the current camera frustum
virtual void getCurrentFrustum(uint cid, NL3D::UCamera *camera) const = 0;
/// Gets the current camera matrix
virtual void getCurrentMatrix(uint cid, NL3D::UCamera *camera) const = 0;
/// At the start of a new render target
virtual bool wantClear() = 0;
/// The 3D scene
virtual bool wantScene() = 0;
/// Interface within the 3D scene
virtual bool wantInterface3D() = 0;
/// 2D Interface
virtual bool wantInterface2D() = 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);
static void listDevices(std::vector<CStereoDeviceInfo> &devicesOut);
static IStereoDisplay *createDevice(const CStereoDeviceInfo &deviceInfo);
static void releaseUnusedLibraries();
static void releaseAllLibraries();
}; /* class IStereoDisplay */
} /* namespace NL3D */
#endif /* #ifndef NL3D_STEREO_DISPLAY_H */
/* end of file */

View file

@ -0,0 +1,73 @@
/**
* \file stereo_hmd.h
* \brief IStereoHMD
* \date 2013-06-27 16:30GMT
* \author Jan Boon (Kaetemi)
* IStereoHMD
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef NL3D_STEREO_HMD_H
#define NL3D_STEREO_HMD_H
#include <nel/misc/types_nl.h>
// STL includes
// NeL includes
// Project includes
#include <nel/3d/stereo_display.h>
namespace NL3D {
/**
* \brief IStereoHMD
* \date 2013-06-27 16:30GMT
* \author Jan Boon (Kaetemi)
* IStereoHMD
*/
class IStereoHMD : public IStereoDisplay
{
public:
IStereoHMD();
virtual ~IStereoHMD();
/// Get the HMD orientation
virtual NLMISC::CQuat getOrientation() const = 0;
/// Get GUI center (1 = width, 1 = height, 0 = center)
virtual void getInterface2DShift(uint cid, float &x, float &y, float distance) const = 0;
/// Set the head model, eye position relative to orientation point
virtual void setEyePosition(const NLMISC::CVector &v) = 0;
/// Get the head model, eye position relative to orientation point
virtual const NLMISC::CVector &getEyePosition() const = 0;
/// Set the scale of the game in units per meter
virtual void setScale(float s) = 0;
}; /* class IStereoHMD */
} /* namespace NL3D */
#endif /* #ifndef NL3D_STEREO_HMD_H */
/* end of file */

View file

@ -0,0 +1,160 @@
/**
* \file stereo_libvr.h
* \brief CStereoLibVR
* \date 2013-08-19 19:17MT
* \author Thibaut Girka (ThibG)
* CStereoLibVR
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef NL3D_STEREO_LIBVR_H
#define NL3D_STEREO_LIBVR_H
#ifdef HAVE_LIBVR
#include <nel/misc/types_nl.h>
// STL includes
// NeL includes
#include <nel/misc/smart_ptr.h>
#include <nel/misc/geom_ext.h>
// Project includes
#include <nel/3d/stereo_hmd.h>
#include <nel/3d/frustum.h>
#include <nel/3d/viewport.h>
#include <nel/3d/u_material.h>
namespace NL3D {
class ITexture;
class CTextureUser;
class CStereoLibVRDevicePtr;
class CStereoLibVRDeviceHandle;
class CPixelProgram;
#define NL_STEREO_MAX_USER_CAMERAS 8
/**
* \brief CStereoOVR
* \date 2013-06-25 22:22GMT
* \author Jan Boon (Kaetemi)
* CStereoOVR
*/
class CStereoLibVR : public IStereoHMD
{
public:
CStereoLibVR(const CStereoLibVRDeviceHandle *handle);
virtual ~CStereoLibVR();
/// Sets driver and generates necessary render targets
virtual void setDriver(NL3D::UDriver *driver);
/// 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;
/// 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();
/// Interface within the 3D scene
virtual bool wantInterface3D();
/// 2D Interface
virtual bool wantInterface2D();
/// 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;
/// 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);
static void listDevices(std::vector<CStereoDeviceInfo> &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:
CStereoLibVRDevicePtr *m_DevicePtr;
int m_Stage;
int m_SubStage;
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];
CMatrix m_CameraMatrix[NL_STEREO_MAX_USER_CAMERAS];
mutable bool m_OrientationCached;
mutable NLMISC::CQuat m_OrientationCache;
UDriver *m_Driver;
NLMISC::CSmartPtr<NL3D::ITexture> m_BarrelTex;
NL3D::CTextureUser *m_BarrelTexU;
NL3D::UMaterial m_BarrelMat;
NLMISC::CQuadUV m_BarrelQuadLeft;
NLMISC::CQuadUV m_BarrelQuadRight;
CPixelProgram *m_PixelProgram;
NLMISC::CVector m_EyePosition;
float m_Scale;
}; /* class CStereoLibVR */
} /* namespace NL3D */
#endif /* HAVE_LIBVR */
#endif /* #ifndef NL3D_STEREO_LIBVR_H */
/* end of file */

View file

@ -0,0 +1,176 @@
/**
* \file stereo_ovr.h
* \brief CStereoOVR
* \date 2013-06-25 22:22GMT
* \author Jan Boon (Kaetemi)
* CStereoOVR
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*
* 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_H
#define NL3D_STEREO_OVR_H
#ifdef HAVE_LIBOVR
#include <nel/misc/types_nl.h>
// STL includes
// NeL includes
#include <nel/misc/smart_ptr.h>
#include <nel/misc/geom_ext.h>
// Project includes
#include <nel/3d/stereo_hmd.h>
#include <nel/3d/frustum.h>
#include <nel/3d/viewport.h>
#include <nel/3d/u_material.h>
namespace NL3D {
class ITexture;
class CTextureUser;
class CStereoOVRDevicePtr;
class CStereoOVRDeviceHandle;
class CPixelProgramOVR;
#define NL_STEREO_MAX_USER_CAMERAS 8
/**
* \brief CStereoOVR
* \date 2013-06-25 22:22GMT
* \author Jan Boon (Kaetemi)
* CStereoOVR
*/
class CStereoOVR : public IStereoHMD
{
public:
CStereoOVR(const CStereoOVRDeviceHandle *handle);
virtual ~CStereoOVR();
/// Sets driver and generates necessary render targets
virtual void setDriver(NL3D::UDriver *driver);
/// 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;
/// 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();
/// Interface within the 3D scene
virtual bool wantInterface3D();
/// 2D Interface
virtual bool wantInterface2D();
/// 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;
/// 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);
static void listDevices(std::vector<CStereoDeviceInfo> &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_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];
CMatrix m_CameraMatrix[NL_STEREO_MAX_USER_CAMERAS];
mutable bool m_OrientationCached;
mutable NLMISC::CQuat m_OrientationCache;
UDriver *m_Driver;
NLMISC::CSmartPtr<NL3D::ITexture> m_BarrelTex;
NL3D::CTextureUser *m_BarrelTexU;
NL3D::UMaterial m_BarrelMat;
NLMISC::CQuadUV m_BarrelQuadLeft;
NLMISC::CQuadUV m_BarrelQuadRight;
NLMISC::CRefPtr<CPixelProgramOVR> m_PixelProgram;
NLMISC::CVector m_EyePosition;
float m_Scale;
}; /* class CStereoOVR */
} /* namespace NL3D */
#endif /* HAVE_LIBOVR */
#endif /* #ifndef NL3D_STEREO_OVR_H */
/* end of file */

View file

@ -168,6 +168,7 @@ public:
*/
// @{
virtual void disableHardwareVertexProgram()=0;
virtual void disableHardwarePixelProgram()=0;
virtual void disableHardwareVertexArrayAGP()=0;
virtual void disableHardwareTextureShader()=0;
// @}
@ -672,13 +673,6 @@ public:
*/
virtual void forceTextureResize(uint divisor)=0;
/** Sets enforcement of native fragment programs. This is by default enabled.
*
* \param nativeOnly If set to false, fragment programs don't need to be native to stay loaded,
* otherwise (aka if true) they will be purged.
*/
virtual void forceNativeFragmentPrograms(bool nativeOnly) = 0;
/** Setup monitor color properties.
*
* Return false if setup failed.

View file

@ -48,6 +48,7 @@ class CVegetableLightEx;
// default distance is 60 meters.
#define NL3D_VEGETABLE_DEFAULT_DIST_MAX 60.f
class CVertexProgramVeget;
// ***************************************************************************
/**
@ -306,7 +307,8 @@ private:
// The same, but no VBHard.
CVegetableVBAllocator _VBSoftAllocator[CVegetableVBAllocator::VBTypeCount];
// Vertex Program. One VertexProgram for each rdrPass (with / without fog)
CVertexProgram *_VertexProgram[NL3D_VEGETABLE_NRDRPASS][2];
CSmartPtr<CVertexProgramVeget> _VertexProgram[NL3D_VEGETABLE_NRDRPASS][2];
CRefPtr<CVertexProgramVeget> _ActiveVertexProgram;
// Material. Useful for texture and alphaTest
@ -342,7 +344,7 @@ private:
/// setup the vertexProgram constants.
void setupVertexProgramConstants(IDriver *driver);
void setupVertexProgramConstants(IDriver *driver, bool fogEnabled);
/** swap the RdrPass type (hard or soft) of the rdrPass of an instance group.

View file

@ -19,90 +19,24 @@
#include "nel/misc/types_nl.h"
#include "nel/misc/smart_ptr.h"
#include "nel/3d/program.h"
#include <list>
namespace NL3D {
// List typedef.
class IDriver;
class IVertexProgramDrvInfos;
typedef std::list<IVertexProgramDrvInfos*> TVtxPrgDrvInfoPtrList;
typedef TVtxPrgDrvInfoPtrList::iterator ItVtxPrgDrvInfoPtrList;
// Class for interaction of vertex program with Driver.
// IVertexProgramDrvInfos represent the real data of the vertex program, stored into the driver (eg: just a GLint for opengl).
class IVertexProgramDrvInfos : public NLMISC::CRefCount
{
private:
IDriver *_Driver;
ItVtxPrgDrvInfoPtrList _DriverIterator;
public:
IVertexProgramDrvInfos (IDriver *drv, ItVtxPrgDrvInfoPtrList it);
// The virtual dtor is important.
virtual ~IVertexProgramDrvInfos(void);
};
/**
* This class is a vertex program.
*
* D3D / OPENGL compatibility notes:
* ---------------------------------
*
* To make your program compatible with D3D and OPENGL nel drivers, please follow thoses directives to write your vertex programs
*
* - Use only v[0], v[1] etc.. syntax for input registers. Don't use v0, v1 or v[OPOS] etc..
* - Use only c[0], c[1] etc.. syntax for constant registers. Don't use c0, c1 etc..
* - Use only o[HPOS], o[COL0] etc.. syntax for output registers. Don't use oPos, oD0 etc..
* - Use only uppercase for registers R1, R2 etc.. Don't use lowercase r1, r2 etc..
* - Use a semicolon to delineate instructions.
* - Use ARL instruction to load the adress register and not MOV.
* - Don't use the NOP instruction.
* - Don't use macros.
*
* -> Thoses programs work without any change under OpenGL.
* -> Direct3D driver implementation will have to modify the syntax on the fly before the setup like this:
* - "v[0]" must be changed in "v0" etc..
* - "o[HPOS]" must be changed in oPos etc..
* - Semicolon must be changed in line return character.
* - ARL instruction must be changed in MOV.
*
* Behaviour of LOG may change depending on implementation: You can only expect to have dest.z = log2(abs(src.w)).
* LIT may or may not clamp the specular exponent to [-128, 128] (not done when EXT_vertex_shader is used for example ..)
*
* Depending on the implementation, some optimizations can be achieved by masking the unused output values of instructions
* as LIT, EXPP ..
*
* \author Cyril 'Hulud' Corvazier
* \author Nevrax France
* \date 2001
*/
class CVertexProgram : public NLMISC::CRefCount
class CVertexProgram : public IProgram
{
public:
/// Constructor
CVertexProgram (const char* program);
CVertexProgram();
CVertexProgram(const char *nelvp);
/// Destructor
virtual ~CVertexProgram ();
/// Get the program
const std::string& getProgram () const { return _Program; };
private:
/// The progam
std::string _Program;
public:
/// The driver information. For the driver implementation only.
NLMISC::CRefPtr<IVertexProgramDrvInfos> _DrvInfo;
};
} // NL3D

View file

@ -21,6 +21,40 @@
#include <vector>
/**
* This class is a vertex program.
*
* D3D / OPENGL compatibility notes:
* ---------------------------------
*
* To make your program compatible with D3D and OPENGL nel drivers, please follow thoses directives to write your vertex programs
*
* - Use only v[0], v[1] etc.. syntax for input registers. Don't use v0, v1 or v[OPOS] etc..
* - Use only c[0], c[1] etc.. syntax for constant registers. Don't use c0, c1 etc..
* - Use only o[HPOS], o[COL0] etc.. syntax for output registers. Don't use oPos, oD0 etc..
* - Use only uppercase for registers R1, R2 etc.. Don't use lowercase r1, r2 etc..
* - Use a semicolon to delineate instructions.
* - Use ARL instruction to load the adress register and not MOV.
* - Don't use the NOP instruction.
* - Don't use macros.
*
* -> Thoses programs work without any change under OpenGL.
* -> Direct3D driver implementation will have to modify the syntax on the fly before the setup like this:
* - "v[0]" must be changed in "v0" etc..
* - "o[HPOS]" must be changed in oPos etc..
* - Semicolon must be changed in line return character.
* - ARL instruction must be changed in MOV.
*
* Behaviour of LOG may change depending on implementation: You can only expect to have dest.z = log2(abs(src.w)).
* LIT may or may not clamp the specular exponent to [-128, 128] (not done when EXT_vertex_shader is used for example ..)
*
* Depending on the implementation, some optimizations can be achieved by masking the unused output values of instructions
* as LIT, EXPP ..
*
* \author Cyril 'Hulud' Corvazier
* \author Nevrax France
* \date 2001
*/
/// Swizzle of an operand in a vertex program
struct CVPSwizzle

View file

@ -49,6 +49,29 @@ const NLMISC::CClassId WaveMakerModelClassId = NLMISC::CClassId(0x16da3356, 0x7
const uint WATER_VERTEX_HARD_SIZE = sizeof(float[3]);
const uint WATER_VERTEX_SOFT_SIZE = sizeof(float[5]);
// VP Water No Wave
class CVertexProgramWaterVPNoWave : public CVertexProgram
{
public:
struct CIdx
{
uint BumpMap0Scale;
uint BumpMap0Offset;
uint BumpMap1Scale;
uint BumpMap1Offset;
uint ObserverHeight;
uint ScaleReflectedRay;
uint DiffuseMapVector0;
uint DiffuseMapVector1;
};
CVertexProgramWaterVPNoWave(bool diffuse);
virtual ~CVertexProgramWaterVPNoWave() { }
virtual void buildInfo();
inline const CIdx &idx() const { return m_Idx; }
private:
CIdx m_Idx;
bool m_Diffuse;
};
/**
* A water shape.
@ -247,17 +270,17 @@ private:
static bool _GridSizeTouched;
//
static std::auto_ptr<CVertexProgram> _VertexProgramBump1;
static std::auto_ptr<CVertexProgram> _VertexProgramBump2;
static NLMISC::CSmartPtr<CVertexProgram> _VertexProgramBump1;
static NLMISC::CSmartPtr<CVertexProgram> _VertexProgramBump2;
//
static std::auto_ptr<CVertexProgram> _VertexProgramBump1Diffuse;
static std::auto_ptr<CVertexProgram> _VertexProgramBump2Diffuse;
static NLMISC::CSmartPtr<CVertexProgram> _VertexProgramBump1Diffuse;
static NLMISC::CSmartPtr<CVertexProgram> _VertexProgramBump2Diffuse;
//
static std::auto_ptr<CVertexProgram> _VertexProgramNoBump;
static std::auto_ptr<CVertexProgram> _VertexProgramNoBumpDiffuse;
static NLMISC::CSmartPtr<CVertexProgram> _VertexProgramNoBump;
static NLMISC::CSmartPtr<CVertexProgram> _VertexProgramNoBumpDiffuse;
//
static std::auto_ptr<CVertexProgram> _VertexProgramNoWave;
static std::auto_ptr<CVertexProgram> _VertexProgramNoWaveDiffuse;
static NLMISC::CSmartPtr<CVertexProgramWaterVPNoWave> _VertexProgramNoWave;
static NLMISC::CSmartPtr<CVertexProgramWaterVPNoWave> _VertexProgramNoWaveDiffuse;
};

View file

@ -153,8 +153,6 @@ SOURCE_GROUP(Driver FILES
../../include/nel/3d/scene.h
scene_group.cpp
../../include/nel/3d/scene_group.h
shader.cpp
../../include/nel/3d/shader.h
texture.cpp
../../include/nel/3d/texture.h
vertex_buffer.cpp
@ -164,7 +162,15 @@ SOURCE_GROUP(Driver FILES
vertex_program.cpp
../../include/nel/3d/vertex_program.h
vertex_program_parse.cpp
../../include/nel/3d/vertex_program_parse.h)
../../include/nel/3d/vertex_program_parse.h
pixel_program.cpp
../../include/nel/3d/pixel_program.h
geometry_program.cpp
../../include/nel/3d/geometry_program.h
program.cpp
../../include/nel/3d/program.h
gpu_program_params.cpp
../../include/nel/3d/gpu_program_params.h)
SOURCE_GROUP(Font FILES
computed_string.cpp
@ -686,12 +692,24 @@ SOURCE_GROUP(Shadows FILES
../../include/nel/3d/shadow_map_manager.h
shadow_poly_receiver.cpp
../../include/nel/3d/shadow_poly_receiver.h)
SOURCE_GROUP(Stereo FILES
stereo_display.cpp
../../include/nel/3d/stereo_display.h
stereo_hmd.cpp
../../include/nel/3d/stereo_hmd.h
stereo_ovr.cpp
stereo_ovr_fp.cpp
../../include/nel/3d/stereo_ovr.h
stereo_libvr.cpp
../../include/nel/3d/stereo_libvr.h
stereo_debugger.cpp
../../include/nel/3d/stereo_debugger.h)
NL_TARGET_LIB(nel3d ${HEADERS} ${SRC})
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR} ${FREETYPE_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR} ${FREETYPE_INCLUDE_DIRS} ${LIBOVR_INCLUDE_DIR} ${LIBVR_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(nel3d nelmisc ${FREETYPE_LIBRARIES})
TARGET_LINK_LIBRARIES(nel3d nelmisc ${FREETYPE_LIBRARIES} ${LIBOVR_LIBRARIES} ${LIBVR_LIBRARY})
SET_TARGET_PROPERTIES(nel3d PROPERTIES LINK_INTERFACE_LIBRARIES "")
NL_DEFAULT_PROPS(nel3d "NeL, Library: NeL 3D")
NL_ADD_RUNTIME_FLAGS(nel3d)
@ -701,6 +719,9 @@ NL_ADD_LIB_SUFFIX(nel3d)
ADD_DEFINITIONS(${LIBXML2_DEFINITIONS})
ADD_DEFINITIONS(${LIBOVR_DEFINITIONS})
ADD_DEFINITIONS(${LIBVR_DEFINITIONS})
IF(WITH_PCH)
ADD_NATIVE_PRECOMPILED_HEADER(nel3d ${CMAKE_CURRENT_SOURCE_DIR}/std3d.h ${CMAKE_CURRENT_SOURCE_DIR}/std3d.cpp)
ENDIF(WITH_PCH)

View file

@ -55,13 +55,18 @@ static const char *TextureOffset =
END \n";
static CVertexProgram TextureOffsetVertexProgram(TextureOffset);
static NLMISC::CSmartPtr<CVertexProgram> TextureOffsetVertexProgram;
//-----------------------------------------------------------------------------------------------------------
CBloomEffect::CBloomEffect()
{
if (!TextureOffsetVertexProgram)
{
TextureOffsetVertexProgram = new CVertexProgram(TextureOffset);
}
_Driver = NULL;
_Scene = NULL;
_SquareBloom = true;
@ -285,6 +290,8 @@ void CBloomEffect::initBloom() // clientcfg
if(!_Init)
init();
_OriginalRenderTarget = static_cast<CDriverUser *>(_Driver)->getDriver()->getRenderTarget();
// if window resize, reinitialize textures
if(_WndWidth!=_Driver->getWindowWidth() || _WndHeight!=_Driver->getWindowHeight())
{
@ -349,13 +356,15 @@ void CBloomEffect::initBloom() // clientcfg
}
}
NL3D::CTextureUser *txt = (_InitBloomEffect) ? (new CTextureUser(_InitText)) : (new CTextureUser());
if(!((CDriverUser *) _Driver)->setRenderTarget(*txt, 0, 0, _WndWidth, _WndHeight))
if (!_OriginalRenderTarget)
{
nlwarning("setRenderTarget return false with initial texture for bloom effect\n");
return;
NL3D::CTextureUser txt = (_InitBloomEffect) ? (CTextureUser(_InitText)) : (CTextureUser());
if(!(static_cast<CDriverUser *>(_Driver)->setRenderTarget(txt, 0, 0, _WndWidth, _WndHeight)))
{
nlwarning("setRenderTarget return false with initial texture for bloom effect\n");
return;
}
}
delete txt;
}
//-----------------------------------------------------------------------------------------------------------
@ -371,13 +380,13 @@ void CBloomEffect::endBloom() // clientcfg
if(_Driver->getWindowWidth()==0 || _Driver->getWindowHeight()==0)
return;
CTextureUser *txt1 = (_InitBloomEffect) ? (new CTextureUser(_InitText)) : (new CTextureUser());
CTextureUser *txt2 = new CTextureUser(_BlurFinalTex);
CRect *rect1 = new CRect(0, 0, _WndWidth, _WndHeight);
CRect *rect2 = new CRect(0, 0, _BlurWidth, _BlurHeight);
CTextureUser txt1 = _OriginalRenderTarget ? CTextureUser(_OriginalRenderTarget) : ((_InitBloomEffect) ? (CTextureUser(_InitText)) : (CTextureUser()));
CTextureUser txt2(_BlurFinalTex);
CRect rect1(0, 0, _WndWidth, _WndHeight);
CRect rect2(0, 0, _BlurWidth, _BlurHeight);
// stretch rect
((CDriverUser *) _Driver)->stretchRect(_Scene, *txt1 , *rect1,
*txt2, *rect2);
((CDriverUser *) _Driver)->stretchRect(_Scene, txt1 , rect1,
txt2, rect2);
// horizontal blur pass
doBlur(true);
@ -387,10 +396,6 @@ void CBloomEffect::endBloom() // clientcfg
// apply blur with a blend operation
applyBlur();
delete txt1;
delete txt2;
delete rect1;
delete rect2;
}
//-----------------------------------------------------------------------------------------------------------
@ -399,16 +404,30 @@ void CBloomEffect::applyBlur()
{
NL3D::IDriver *drvInternal = ((CDriverUser *) _Driver)->getDriver();
// in opengl, display in init texture
if(_InitBloomEffect)
/*if (_OriginalRenderTarget)
{
CTextureUser *txt = new CTextureUser(_InitText);
if(!((CDriverUser *) _Driver)->setRenderTarget(*txt, 0, 0, _WndWidth, _WndHeight))
CTextureUser txt(_OriginalRenderTarget);
if(!(static_cast<CDriverUser *>(_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<CDriverUser *>(_Driver)->setRenderTarget(txt, 0, 0, _WndWidth, _WndHeight)))
{
nlwarning("setRenderTarget return false with initial texture for bloom effect\n");
return;
}
delete txt;
}*/
CTextureUser txtApply = _OriginalRenderTarget ? CTextureUser(_OriginalRenderTarget) : ((_InitBloomEffect) ? (CTextureUser(_InitText)) : (CTextureUser()));
if(!(static_cast<CDriverUser *>(_Driver)->setRenderTarget(txtApply, 0, 0, _WndWidth, _WndHeight)))
{
nlwarning("setRenderTarget return false with initial texture for bloom effect\n");
return;
}
// display blur texture
@ -429,9 +448,9 @@ void CBloomEffect::applyBlur()
}
// initialize vertex program
drvInternal->activeVertexProgram(&TextureOffsetVertexProgram);
drvInternal->setConstant(8, 255.f, 255.f, 255.f, 255.f);
drvInternal->setConstant(9, 0.0f, 0.f, 0.f, 1.f);
drvInternal->activeVertexProgram(TextureOffsetVertexProgram);
drvInternal->setUniform4f(IDriver::VertexProgram, 8, 255.f, 255.f, 255.f, 255.f);
drvInternal->setUniform4f(IDriver::VertexProgram, 9, 0.0f, 0.f, 0.f, 1.f);
// initialize blur material
UMaterial displayBlurMat;
@ -463,7 +482,9 @@ void CBloomEffect::applyBlur()
void CBloomEffect::endInterfacesDisplayBloom() // clientcfg
{
if(_InitBloomEffect)
// 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;
@ -475,9 +496,8 @@ void CBloomEffect::endInterfacesDisplayBloom() // clientcfg
return;
NL3D::IDriver *drvInternal = ((CDriverUser *) _Driver)->getDriver();
CTextureUser *txt = new CTextureUser();
((CDriverUser *)_Driver)->setRenderTarget(*txt, 0, 0, 0, 0);
delete txt;
CTextureUser txtNull;
((CDriverUser *)_Driver)->setRenderTarget(txtNull, 0, 0, 0, 0);
// initialize texture coordinates
float newU = drvInternal->isTextureRectangle(_InitText) ? (float)_WndWidth : 1.f;
@ -497,6 +517,8 @@ void CBloomEffect::endInterfacesDisplayBloom() // clientcfg
_Driver->drawQuad(_DisplayQuad, _DisplayInitMat);
_Driver->setMatrixMode3D(pCam);
}
_OriginalRenderTarget = NULL;
}
@ -523,19 +545,18 @@ void CBloomEffect::doBlur(bool horizontalBlur)
}
NL3D::IDriver *drvInternal = ((CDriverUser *) _Driver)->getDriver();
CTextureUser *txt = new CTextureUser(endTexture);
CTextureUser txt(endTexture);
// initialize render target
if(!((CDriverUser *) _Driver)->setRenderTarget(*txt, 0, 0, _BlurWidth, _BlurHeight))
if(!((CDriverUser *) _Driver)->setRenderTarget(txt, 0, 0, _BlurWidth, _BlurHeight))
{
nlwarning("setRenderTarget return false with blur texture for bloom effect\n");
return;
}
delete txt;
// initialize vertex program
drvInternal->activeVertexProgram(&TextureOffsetVertexProgram);
drvInternal->setConstant(8, 255.f, 255.f, 255.f, 255.f);
drvInternal->setConstant(9, 0.0f, 0.f, 0.f, 1.f);
drvInternal->activeVertexProgram(TextureOffsetVertexProgram);
drvInternal->setUniform4f(IDriver::VertexProgram, 8, 255.f, 255.f, 255.f, 255.f);
drvInternal->setUniform4f(IDriver::VertexProgram, 9, 0.0f, 0.f, 0.f, 1.f);
// 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.
@ -554,10 +575,10 @@ void CBloomEffect::doBlur(bool horizontalBlur)
decalR = 1.f;
decal2R = 2.f;
}
drvInternal->setConstant(10, (decalR/(float)_BlurWidth)*blurVec.x, (decalR/(float)_BlurHeight)*blurVec.y, 0.f, 0.f);
drvInternal->setConstant(11, (decal2R/(float)_BlurWidth)*blurVec.x, (decal2R/(float)_BlurHeight)*blurVec.y, 0.f, 0.f);
drvInternal->setConstant(12, (decalL/(float)_BlurWidth)*blurVec.x, (decalL/(float)_BlurHeight)*blurVec.y, 0.f, 0.f);
drvInternal->setConstant(13, (decal2L/(float)_BlurWidth)*blurVec.x, (decal2L/(float)_BlurHeight)*blurVec.y, 0.f, 0.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);
drvInternal->setUniform2f(IDriver::VertexProgram, 13, (decal2L/(float)_BlurWidth)*blurVec.x, (decal2L/(float)_BlurHeight)*blurVec.y);
// initialize material textures
CMaterial * matObject = _BlurMat.getObjectPtr();
@ -579,10 +600,9 @@ void CBloomEffect::doBlur(bool horizontalBlur)
// disable render target and vertex program
drvInternal->activeVertexProgram(NULL);
txt = new CTextureUser();
((CDriverUser *)_Driver)->setRenderTarget(*txt, 0, 0, 0, 0);
CTextureUser cu;
((CDriverUser *)_Driver)->setRenderTarget(cu, 0, 0, 0, 0);
_Driver->setMatrixMode3D(pCam);
delete txt;
}
}; // NL3D

View file

@ -21,6 +21,7 @@
#include "nel/3d/index_buffer.h"
#include "nel/3d/material.h"
#include "nel/3d/frustum.h"
#include "nel/3d/viewport.h"
#include "nel/misc/smart_ptr.h"
#include "nel/misc/debug.h"
@ -85,6 +86,10 @@ void CComputedString::render2D (IDriver& driver,
// get window size
uint32 wndWidth, wndHeight;
driver.getWindowSize(wndWidth, wndHeight);
CViewport vp;
driver.getViewport(vp);
wndWidth = (uint32)((float)wndWidth * vp.getWidth());
wndHeight = (uint32)((float)wndHeight * vp.getHeight());
// scale to window size.
x*= wndWidth;
z*= wndHeight;

View file

@ -20,7 +20,6 @@
#include "nel/misc/types_nl.h"
#include "nel/3d/driver.h"
#include "nel/3d/shader.h"
#include "nel/3d/vertex_buffer.h"
#include "nel/misc/algo.h"
@ -33,7 +32,7 @@ namespace NL3D
{
// ***************************************************************************
const uint32 IDriver::InterfaceVersion = 0x6b; // added anisotropic filter
const uint32 IDriver::InterfaceVersion = 0x6d; // gpu program interface
// ***************************************************************************
IDriver::IDriver() : _SyncTexDrvInfos( "IDriver::_SyncTexDrvInfos" )
@ -58,7 +57,7 @@ IDriver::~IDriver()
nlassert(_MatDrvInfos.size()==0);
nlassert(_VBDrvInfos.size()==0);
nlassert(_IBDrvInfos.size()==0);
nlassert(_VtxPrgDrvInfos.size()==0);
nlassert(_GPUPrgDrvInfos.size()==0);
}
@ -95,14 +94,6 @@ bool IDriver::release(void)
delete *itmat;
}
// Release Shader drv.
ItShaderDrvInfoPtrList itshd;
while( (itshd = _ShaderDrvInfos.begin()) != _ShaderDrvInfos.end() )
{
// NB: at IShader deletion, this->_MatDrvInfos is updated (entry deleted);
delete *itshd;
}
// Release VBs drv.
ItVBDrvInfoPtrList itvb;
while( (itvb = _VBDrvInfos.begin()) != _VBDrvInfos.end() )
@ -119,12 +110,12 @@ bool IDriver::release(void)
delete *itib;
}
// Release VtxPrg drv.
ItVtxPrgDrvInfoPtrList itVtxPrg;
while( (itVtxPrg = _VtxPrgDrvInfos.begin()) != _VtxPrgDrvInfos.end() )
// Release GPUPrg drv.
ItGPUPrgDrvInfoPtrList itGPUPrg;
while( (itGPUPrg = _GPUPrgDrvInfos.begin()) != _GPUPrgDrvInfos.end() )
{
// NB: at IVertexProgramDrvInfos deletion, this->_VtxPrgDrvInfos is updated (entry deleted);
delete *itVtxPrg;
// NB: at IVertexProgramDrvInfos deletion, this->_GPUPrgDrvInfos is updated (entry deleted);
delete *itGPUPrg;
}
return true;
@ -249,14 +240,9 @@ void IDriver::removeMatDrvInfoPtr(ItMatDrvInfoPtrList shaderIt)
_MatDrvInfos.erase(shaderIt);
}
// ***************************************************************************
void IDriver::removeShaderDrvInfoPtr(ItShaderDrvInfoPtrList shaderIt)
void IDriver::removeGPUPrgDrvInfoPtr(ItGPUPrgDrvInfoPtrList gpuPrgDrvInfoIt)
{
_ShaderDrvInfos.erase(shaderIt);
}
// ***************************************************************************
void IDriver::removeVtxPrgDrvInfoPtr(ItVtxPrgDrvInfoPtrList vtxPrgDrvInfoIt)
{
_VtxPrgDrvInfos.erase(vtxPrgDrvInfoIt);
_GPUPrgDrvInfos.erase(gpuPrgDrvInfoIt);
}
// ***************************************************************************

View file

@ -193,6 +193,11 @@ CDriverD3D::CDriverD3D()
#else // NL_DISABLE_HARDWARE_VERTEX_PROGAM
_DisableHardwareVertexProgram = false;
#endif // NL_DISABLE_HARDWARE_VERTEX_PROGAM
#ifdef NL_DISABLE_HARDWARE_PIXEL_PROGAM
_DisableHardwarePixelProgram = true;
#else // NL_DISABLE_HARDWARE_PIXEL_PROGAM
_DisableHardwarePixelProgram = false;
#endif // NL_DISABLE_HARDWARE_PIXEL_PROGAM
#ifdef NL_DISABLE_HARDWARE_VERTEX_ARRAY_AGP
_DisableHardwareVertexArrayAGP = true;
#else // NL_DISABLE_HARDWARE_VERTEX_ARRAY_AGP
@ -1546,13 +1551,15 @@ bool CDriverD3D::setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool r
#endif // NL_FORCE_TEXTURE_STAGE_COUNT
_VertexProgram = !_DisableHardwareVertexProgram && ((caps.VertexShaderVersion&0xffff) >= 0x0100);
_PixelShader = !_DisableHardwarePixelShader && (caps.PixelShaderVersion&0xffff) >= 0x0101;
_PixelProgramVersion = _DisableHardwareVertexProgram ? 0x0000 : caps.PixelShaderVersion & 0xffff;
nldebug("Pixel Program Version: %i.%i", (uint32)((_PixelProgramVersion & 0xFF00) >> 8), (uint32)(_PixelProgramVersion & 0xFF));
_PixelProgram = _PixelProgramVersion >= 0x0101;
_MaxVerticesByVertexBufferHard = caps.MaxVertexIndex;
_MaxLight = caps.MaxActiveLights;
if(_MaxLight > 0xFF) _MaxLight = 3;
if (_PixelShader)
if (_PixelProgram)
{
_MaxNumPerStageConstantLighted = _NbNeLTextureStages;
_MaxNumPerStageConstantUnlighted = _NbNeLTextureStages;
@ -1703,6 +1710,13 @@ bool CDriverD3D::release()
// Call IDriver::release() before, to destroy textures, shaders and VBs...
IDriver::release();
ItShaderDrvInfoPtrList itshd;
while( (itshd = _ShaderDrvInfos.begin()) != _ShaderDrvInfos.end() )
{
// NB: at IShader deletion, this->_MatDrvInfos is updated (entry deleted);
delete *itshd;
}
_SwapBufferCounter = 0;
if (_QuadIB)
@ -2016,6 +2030,8 @@ bool CDriverD3D::swapBuffers()
// Reset vertex program
setVertexProgram (NULL, NULL);
// Reset pixel program
setPixelShader (NULL);
if (_VBHardProfiling)
{
@ -2987,7 +3003,7 @@ bool CDriverD3D::stretchRect(ITexture * srcText, NLMISC::CRect &srcRect, ITextur
bool CDriverD3D::supportBloomEffect() const
{
return isVertexProgramSupported();
return supportVertexProgram();
}
// ***************************************************************************
@ -3330,9 +3346,9 @@ uint COcclusionQueryD3D::getVisibleCount()
}
// ***************************************************************************
bool CDriverD3D::isWaterShaderSupported() const
bool CDriverD3D::supportWaterShader() const
{
H_AUTO_D3D(CDriverD3D_isWaterShaderSupported);
H_AUTO_D3D(CDriverD3D_supportWaterShader);
return _PixelShaderVersion >= D3DPS_VERSION(1, 1);
}
@ -3618,7 +3634,7 @@ void CDriverD3D::CVertexProgramPtrState::apply(CDriverD3D *driver)
void CDriverD3D::CPixelShaderPtrState::apply(CDriverD3D *driver)
{
H_AUTO_D3D(CDriverD3D_CPixelShaderPtrState);
if (!driver->supportPixelShaders()) return;
if (!driver->_PixelProgram) return;
driver->_DeviceInterface->SetPixelShader(PixelShader);
}

View file

@ -35,7 +35,6 @@
#include "nel/3d/scissor.h"
#include "nel/3d/driver.h"
#include "nel/3d/material.h"
#include "nel/3d/shader.h"
#include "nel/3d/vertex_buffer.h"
#include "nel/3d/index_buffer.h"
#include "nel/3d/ptr_set.h"
@ -181,6 +180,75 @@ public:
};
using NLMISC::CRefCount;
class IDriver;
class CDriverD3D;
// List typedef.
class IShaderDrvInfos;
typedef std::list<IShaderDrvInfos*> TShaderDrvInfoPtrList;
typedef TShaderDrvInfoPtrList::iterator ItShaderDrvInfoPtrList;
/**
* Interface for shader driver infos.
*/
class IShaderDrvInfos : public CRefCount
{
private:
CDriverD3D *_Driver;
ItShaderDrvInfoPtrList _DriverIterator;
public:
IShaderDrvInfos(CDriverD3D *drv, ItShaderDrvInfoPtrList it) {_Driver= drv; _DriverIterator= it;}
// The virtual dtor is important.
virtual ~IShaderDrvInfos();
};
/**
* Shader resource for the driver. It is just a container for a ".fx" text file.
*/
/* *** IMPORTANT ********************
* *** IF YOU MODIFY THE STRUCTURE OF THIS CLASS, PLEASE INCREMENT IDriver::InterfaceVersion TO INVALIDATE OLD DRIVER DLL
* **********************************
*/
// --------------------------------------------------
class CD3DShaderFX
{
public:
CD3DShaderFX();
~CD3DShaderFX();
// Load a shader file
bool loadShaderFile (const char *filename);
// Set the shader text
void setText (const char *text);
// Get the shader text
const char *getText () const { return _Text.c_str(); }
// Set the shader name
void setName (const char *name);
// Get the shader name
const char *getName () const { return _Name.c_str(); }
public:
// Private. For Driver only.
bool _ShaderChanged;
NLMISC::CRefPtr<IShaderDrvInfos> _DrvInfo;
private:
// The shader
std::string _Text;
// The shader name
std::string _Name;
};
// ***************************************************************************
class CTextureDrvInfosD3D : public ITextureDrvInfos
{
@ -229,16 +297,48 @@ public:
};
// ***************************************************************************
class CVertexProgamDrvInfosD3D : public IVertexProgramDrvInfos
class CVertexProgamDrvInfosD3D : public IProgramDrvInfos
{
public:
// The shader
IDirect3DVertexShader9 *Shader;
CVertexProgamDrvInfosD3D(IDriver *drv, ItVtxPrgDrvInfoPtrList it);
CVertexProgamDrvInfosD3D(IDriver *drv, ItGPUPrgDrvInfoPtrList it);
~CVertexProgamDrvInfosD3D();
virtual uint getUniformIndex(const char *name) const
{
std::map<std::string, uint>::const_iterator it = ParamIndices.find(name);
if (it != ParamIndices.end()) return it->second;
return ~0;
};
std::map<std::string, uint> ParamIndices;
};
// ***************************************************************************
class CPixelProgramDrvInfosD3D : public IProgramDrvInfos
{
public:
// The shader
IDirect3DPixelShader9 *Shader;
CPixelProgramDrvInfosD3D(IDriver *drv, ItGPUPrgDrvInfoPtrList it);
~CPixelProgramDrvInfosD3D();
virtual uint getUniformIndex(const char *name) const
{
std::map<std::string, uint>::const_iterator it = ParamIndices.find(name);
if (it != ParamIndices.end()) return it->second;
return ~0;
};
std::map<std::string, uint> ParamIndices;
};
@ -333,7 +433,7 @@ public:
// Scalar handles
D3DXHANDLE ScalarFloatHandle[MaxShaderTexture];
CShaderDrvInfosD3D(IDriver *drv, ItShaderDrvInfoPtrList it);
CShaderDrvInfosD3D(CDriverD3D *drv, ItShaderDrvInfoPtrList it);
virtual ~CShaderDrvInfosD3D();
};
@ -773,13 +873,13 @@ public:
// Driver parameters
virtual void disableHardwareVertexProgram();
virtual void disableHardwarePixelProgram();
virtual void disableHardwareIndexArrayAGP();
virtual void disableHardwareVertexArrayAGP();
virtual void disableHardwareTextureShader();
virtual void forceDXTCCompression(bool dxtcComp);
virtual void setAnisotropicFilter(sint filter);
virtual void forceTextureResize(uint divisor);
virtual void forceNativeFragmentPrograms(bool /* nativeOnly */) {} // ignored
// Driver information
virtual uint getNumAdapter() const;
@ -841,6 +941,7 @@ public:
// todo hulud d3d buffers
virtual void getZBufferPart (std::vector<float> &zbuffer, NLMISC::CRect &rect);
virtual bool setRenderTarget (ITexture *tex, uint32 x, uint32 y, uint32 width, uint32 height, uint32 mipmapLevel, uint32 cubeFace);
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 getRenderTargetSize (uint32 &width, uint32 &height);
@ -959,9 +1060,9 @@ public:
virtual bool supportTextureShaders() const {return false;};
virtual bool supportMADOperator() const;
// todo hulud d3d adressing mode
virtual bool isWaterShaderSupported() const;
virtual bool supportWaterShader() const;
// todo hulud d3d adressing mode
virtual bool isTextureAddrModeSupported(CMaterial::TTexAddressingMode /* mode */) const {return false;};
virtual bool supportTextureAddrMode(CMaterial::TTexAddressingMode /* mode */) const {return false;};
// todo hulud d3d adressing mode
virtual void setMatrix2DForTextureOffsetAddrMode(const uint /* stage */, const float /* mat */[4]) {}
@ -991,18 +1092,133 @@ public:
virtual void setupMaterialPass(uint pass);
virtual void endMaterialMultiPass();
// Vertex program
virtual bool isVertexProgramSupported () const;
virtual bool isVertexProgramEmulated () const;
virtual bool activeVertexProgram (CVertexProgram *program);
virtual void setConstant (uint index, float, float, float, float);
virtual void setConstant (uint index, double, double, double, double);
virtual void setConstant (uint index, const NLMISC::CVector& value);
virtual void setConstant (uint index, const NLMISC::CVectorD& value);
virtual void setConstant (uint index, uint num, const float *src);
virtual void setConstant (uint index, uint num, const double *src);
virtual void setConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform);
virtual void setConstantFog (uint index);
/// \name Vertex Program
// @{
// Order of preference
// - activeVertexProgram
// - CMaterial pass[n] VP (uses activeVertexProgram, but does not override if one already set by code)
// - default generic VP that mimics fixed pipeline / no VP with fixed pipeline
/**
* Does the driver supports vertex program, but emulated by CPU ?
*/
virtual bool isVertexProgramEmulated() const;
/** Return true if the driver supports the specified vertex program profile.
*/
virtual bool supportVertexProgram(CVertexProgram::TProfile profile = CVertexProgram::nelvp) const;
/** Compile the given vertex program, return if successful.
* 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);
/** Set the active vertex program. This will override vertex programs specified in CMaterial render calls.
* Also used internally by setupMaterial(CMaterial) when getVertexProgram returns NULL.
* The vertex program is activated immediately.
*/
virtual bool activeVertexProgram(CVertexProgram *program);
// @}
/// \name Pixel Program
// @{
// Order of preference
// - activePixelProgram
// - CMaterial pass[n] PP (uses activePixelProgram, but does not override if one already set by code)
// - PP generated from CMaterial (uses activePixelProgram, but does not override if one already set by code)
/** Return true if the driver supports the specified pixel program profile.
*/
virtual bool supportPixelProgram(CPixelProgram::TProfile profile) const;
/** Compile the given pixel program, return if successful.
* 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);
/** Set the active pixel program. This will override pixel programs specified in CMaterial render calls.
* Also used internally by setupMaterial(CMaterial) when getPixelProgram returns NULL.
* The pixel program is activated immediately.
*/
virtual bool activePixelProgram(CPixelProgram *program);
// @}
/// \name Geometry Program
// @{
// Order of preference
// - activeGeometryProgram
// - CMaterial pass[n] PP (uses activeGeometryProgram, but does not override if one already set by code)
// - none
/** Return true if the driver supports the specified pixel program profile.
*/
virtual bool supportGeometryProgram(CGeometryProgram::TProfile profile) const { return false; }
/** Compile the given pixel program, return if successful.
* 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) { return false; }
/** Set the active pixel program. This will override pixel programs specified in CMaterial render calls.
* Also used internally by setupMaterial(CMaterial) when getGeometryProgram returns NULL.
* The pixel program is activated immediately.
*/
virtual bool activeGeometryProgram(CGeometryProgram *program) { return false; }
// @}
/// \name Program parameters
// @{
// Set parameters
virtual void setUniform1f(TProgram program, uint index, float f0);
virtual void setUniform2f(TProgram program, uint index, float f0, float f1);
virtual void setUniform3f(TProgram program, uint index, float f0, float f1, float f2);
virtual void setUniform4f(TProgram program, uint index, float f0, float f1, float f2, float f3);
virtual void setUniform1i(TProgram program, uint index, sint32 i0);
virtual void setUniform2i(TProgram program, uint index, sint32 i0, sint32 i1);
virtual void setUniform3i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2);
virtual void setUniform4i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3);
virtual void setUniform1ui(TProgram program, uint index, uint32 ui0);
virtual void setUniform2ui(TProgram program, uint index, uint32 ui0, uint32 ui1);
virtual void setUniform3ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2);
virtual void setUniform4ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3);
virtual void setUniform3f(TProgram program, uint index, const NLMISC::CVector& v);
virtual void setUniform4f(TProgram program, uint index, const NLMISC::CVector& v, float f3);
virtual void setUniform4f(TProgram program, uint index, const NLMISC::CRGBAF& rgba);
virtual void setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m);
virtual void setUniform4fv(TProgram program, uint index, size_t num, const float *src);
virtual void setUniform4iv(TProgram program, uint index, size_t num, const sint32 *src);
virtual void setUniform4uiv(TProgram program, uint index, size_t num, const uint32 *src);
// Set builtin parameters
virtual void setUniformMatrix(TProgram program, uint index, TMatrix matrix, TTransform transform);
virtual void setUniformFog(TProgram program, uint index);
// Set feature parameters
virtual bool setUniformDriver(TProgram program); // set all driver-specific features params (based on program->features->DriverFlags)
virtual bool setUniformMaterial(TProgram program, CMaterial &material); // set all material-specific feature params (based on program->features->MaterialFlags)
virtual void setUniformParams(TProgram program, CGPUProgramParams &params); // set all user-provided params from the storage
virtual bool isUniformProgramState() { return false; }
// @}
virtual void enableVertexProgramDoubleSidedColor(bool doubleSided);
virtual bool supportVertexProgramDoubleSidedColor() const;
@ -1021,7 +1237,7 @@ public:
* ColorOp[n] = DISABLE;
* AlphaOp[n] = DISABLE;
*/
virtual bool activeShader(CShader *shd);
bool activeShader(CD3DShaderFX *shd);
// Bench
virtual void startBench (bool wantStandardDeviation = false, bool quick = false, bool reset = true);
@ -1040,8 +1256,6 @@ public:
uint32 getMaxVertexIndex() const { return _MaxVertexIndex; }
bool supportPixelShaders() const { return _PixelShader; }
// *** Inline info
uint inlGetNumTextStages() const { return _NbNeLTextureStages; }
@ -1892,12 +2106,21 @@ public:
return d3dtex;
}
// Get the d3dtext mirror of an existing setuped pixel program.
static inline CPixelProgramDrvInfosD3D* getPixelProgramD3D(CPixelProgram& pixelProgram)
{
H_AUTO_D3D(CDriverD3D_getPixelProgramD3D);
CPixelProgramDrvInfosD3D* d3dPixelProgram;
d3dPixelProgram = (CPixelProgramDrvInfosD3D*)(IProgramDrvInfos*)(pixelProgram.m_DrvInfo);
return d3dPixelProgram;
}
// Get the d3dtext mirror of an existing setuped vertex program.
static inline CVertexProgamDrvInfosD3D* getVertexProgramD3D(CVertexProgram& vertexProgram)
{
H_AUTO_D3D(CDriverD3D_getVertexProgramD3D);
CVertexProgamDrvInfosD3D* d3dVertexProgram;
d3dVertexProgram = (CVertexProgamDrvInfosD3D*)(IVertexProgramDrvInfos*)(vertexProgram._DrvInfo);
d3dVertexProgram = (CVertexProgamDrvInfosD3D*)(IProgramDrvInfos*)(vertexProgram.m_DrvInfo);
return d3dVertexProgram;
}
@ -1943,7 +2166,7 @@ public:
void releaseInternalShaders();
bool setShaderTexture (uint textureHandle, ITexture *texture, CFXCache *cache);
bool validateShader(CShader *shader);
bool validateShader(CD3DShaderFX *shader);
void activePass (uint pass)
{
@ -2080,6 +2303,8 @@ private:
void findNearestFullscreenVideoMode();
TShaderDrvInfoPtrList _ShaderDrvInfos;
// Windows
std::string _WindowClass;
HWND _HWnd;
@ -2197,8 +2422,10 @@ private:
bool _ForceDXTCCompression:1;
bool _TextureCubeSupported;
bool _VertexProgram;
bool _PixelShader;
bool _PixelProgram;
uint16 _PixelProgramVersion;
bool _DisableHardwareVertexProgram;
bool _DisableHardwarePixelProgram;
bool _DisableHardwareVertexArrayAGP;
bool _DisableHardwareIndexArrayAGP;
bool _DisableHardwarePixelShader;
@ -2316,6 +2543,9 @@ private:
// The last vertex buffer needs vertex color
bool _FogEnabled;
NLMISC::CRefPtr<CVertexProgram> _VertexProgramUser;
NLMISC::CRefPtr<CPixelProgram> _PixelProgramUser;
// *** Internal resources
// Current render pass
@ -2344,7 +2574,7 @@ private:
CIndexBuffer _QuadIndexesAGP;
// The last setuped shader
CShader *_CurrentShader;
CD3DShaderFX *_CurrentShader;
UINT _CurrentShaderPassCount;
public:
struct CTextureRef
@ -2369,29 +2599,29 @@ private:
CRenderVariable *_ModifiedRenderState;
// Internal shaders
CShader _ShaderLightmap0;
CShader _ShaderLightmap1;
CShader _ShaderLightmap2;
CShader _ShaderLightmap3;
CShader _ShaderLightmap4;
CShader _ShaderLightmap0Blend;
CShader _ShaderLightmap1Blend;
CShader _ShaderLightmap2Blend;
CShader _ShaderLightmap3Blend;
CShader _ShaderLightmap4Blend;
CShader _ShaderLightmap0X2;
CShader _ShaderLightmap1X2;
CShader _ShaderLightmap2X2;
CShader _ShaderLightmap3X2;
CShader _ShaderLightmap4X2;
CShader _ShaderLightmap0BlendX2;
CShader _ShaderLightmap1BlendX2;
CShader _ShaderLightmap2BlendX2;
CShader _ShaderLightmap3BlendX2;
CShader _ShaderLightmap4BlendX2;
CShader _ShaderCloud;
CShader _ShaderWaterNoDiffuse;
CShader _ShaderWaterDiffuse;
CD3DShaderFX _ShaderLightmap0;
CD3DShaderFX _ShaderLightmap1;
CD3DShaderFX _ShaderLightmap2;
CD3DShaderFX _ShaderLightmap3;
CD3DShaderFX _ShaderLightmap4;
CD3DShaderFX _ShaderLightmap0Blend;
CD3DShaderFX _ShaderLightmap1Blend;
CD3DShaderFX _ShaderLightmap2Blend;
CD3DShaderFX _ShaderLightmap3Blend;
CD3DShaderFX _ShaderLightmap4Blend;
CD3DShaderFX _ShaderLightmap0X2;
CD3DShaderFX _ShaderLightmap1X2;
CD3DShaderFX _ShaderLightmap2X2;
CD3DShaderFX _ShaderLightmap3X2;
CD3DShaderFX _ShaderLightmap4X2;
CD3DShaderFX _ShaderLightmap0BlendX2;
CD3DShaderFX _ShaderLightmap1BlendX2;
CD3DShaderFX _ShaderLightmap2BlendX2;
CD3DShaderFX _ShaderLightmap3BlendX2;
CD3DShaderFX _ShaderLightmap4BlendX2;
CD3DShaderFX _ShaderCloud;
CD3DShaderFX _ShaderWaterNoDiffuse;
CD3DShaderFX _ShaderWaterDiffuse;
// Backup frame buffer
@ -2527,6 +2757,10 @@ public:
// Clip the wanted rectangle with window. return true if rect is not NULL.
bool clipRect(NLMISC::CRect &rect);
friend class IShaderDrvInfos;
void removeShaderDrvInfoPtr(ItShaderDrvInfoPtrList shaderIt);
};
#define NL_D3DCOLOR_RGBA(rgba) (D3DCOLOR_ARGB(rgba.A,rgba.R,rgba.G,rgba.B))

View file

@ -328,7 +328,7 @@ bool CDriverD3D::setupMaterial(CMaterial &mat)
pShader = static_cast<CMaterialDrvInfosD3D*>((IMaterialDrvInfos*)(mat._MatDrvInfo));
// Now we can get the supported shader from the cache.
CMaterial::TShader matShader = mat.getShader();
CMaterial::TShader matShader = _PixelProgramUser ? CMaterial::Program : mat.getShader();
if (_CurrentMaterialSupportedShader != CMaterial::Normal)
{
@ -567,7 +567,7 @@ bool CDriverD3D::setupMaterial(CMaterial &mat)
normalShaderDesc.TexEnvMode[stage] = mat.getTexEnvMode(uint8(stage));
}
if (_PixelShader)
if (_PixelProgram)
{
#ifdef NL_DEBUG_D3D
// Check, should not occured
@ -648,7 +648,9 @@ 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))
)
{
uint stage;
for(stage=0 ; stage<maxTexture; ++stage)
@ -668,7 +670,9 @@ 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))
)
{
uint stage;
for(stage=0 ; stage<maxTexture; ++stage)
@ -933,7 +937,7 @@ bool CDriverD3D::setupMaterial(CMaterial &mat)
activeShader (NULL);
/* If unlighted trick is needed, set the shader later */
if (!pShader->NeedsConstantForDiffuse && _PixelShader)
if (!pShader->NeedsConstantForDiffuse && _PixelProgram)
setPixelShader (pShader->PixelShader);
}
break;
@ -2019,7 +2023,7 @@ void CDriverD3D::endMaterialMultiPass()
bool CDriverD3D::supportCloudRenderSinglePass () const
{
H_AUTO_D3D(CDriver3D_supportCloudRenderSinglePass);
return _PixelShader;
return _PixelProgram;
}
// ***************************************************************************

View file

@ -0,0 +1,153 @@
/** \file driver_direct3d_pixel_program.cpp
* Direct 3d driver implementation
*
* $Id: driver_direct3d_pixel_program.cpp,v 1.1.2.4 2007/07/09 15:26:35 legallo Exp $
*
* \todo manage better the init/release system (if a throw occurs in the init, we must release correctly the driver)
*/
/* Copyright, 2000 Nevrax Ltd.
*
* This file is part of NEVRAX NEL.
* NEVRAX NEL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
* NEVRAX NEL 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
* General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with NEVRAX NEL; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#include "stddirect3d.h"
#include "driver_direct3d.h"
using namespace std;
using namespace NLMISC;
namespace NL3D
{
// ***************************************************************************
CPixelProgramDrvInfosD3D::CPixelProgramDrvInfosD3D(IDriver *drv, ItGPUPrgDrvInfoPtrList it) : IProgramDrvInfos (drv, it)
{
H_AUTO_D3D(CPixelProgramDrvInfosD3D_CPixelProgamDrvInfosD3D)
Shader = NULL;
}
// ***************************************************************************
CPixelProgramDrvInfosD3D::~CPixelProgramDrvInfosD3D()
{
H_AUTO_D3D(CPixelProgramDrvInfosD3D_CPixelProgramDrvInfosD3DDtor)
if (Shader)
Shader->Release();
}
// ***************************************************************************
bool CDriverD3D::supportPixelProgram (CPixelProgram::TProfile profile) const
{
H_AUTO_D3D(CDriverD3D_supportPixelProgram_profile)
return ((profile & 0xFFFF0000) == 0xD9020000)
&& (_PixelProgramVersion >= (uint16)(profile & 0x0000FFFF));
}
// ***************************************************************************
bool CDriverD3D::compilePixelProgram(CPixelProgram *program)
{
// Program setuped ?
if (program->m_DrvInfo==NULL)
{
// Find a supported pixel program profile
IProgram::CSource *source = NULL;
for (uint i = 0; i < program->getSourceNb(); ++i)
{
if (supportPixelProgram(program->getSource(i)->Profile))
{
source = program->getSource(i);
}
}
if (!source)
{
nlwarning("No supported source profile for pixel program");
return false;
}
_GPUPrgDrvInfos.push_front (NULL);
ItGPUPrgDrvInfoPtrList itPix = _GPUPrgDrvInfos.begin();
CPixelProgramDrvInfosD3D *drvInfo;
*itPix = drvInfo = new CPixelProgramDrvInfosD3D(this, itPix);
// Create a driver info structure
program->m_DrvInfo = *itPix;
LPD3DXBUFFER pShader;
LPD3DXBUFFER pErrorMsgs;
if (D3DXAssembleShader(source->SourcePtr, source->SourceLen, NULL, NULL, 0, &pShader, &pErrorMsgs) == D3D_OK)
{
if (_DeviceInterface->CreatePixelShader((DWORD*)pShader->GetBufferPointer(), &(getPixelProgramD3D(*program)->Shader)) != D3D_OK)
return false;
}
else
{
nlwarning ("Can't assemble pixel program:");
nlwarning ((const char*)pErrorMsgs->GetBufferPointer());
return false;
}
// Set parameters for assembly programs
drvInfo->ParamIndices = source->ParamIndices;
// Build the feature info
program->buildInfo(source);
}
return true;
}
// ***************************************************************************
bool CDriverD3D::activePixelProgram(CPixelProgram *program)
{
H_AUTO_D3D(CDriverD3D_activePixelProgram )
if (_DisableHardwarePixelProgram)
return false;
// Set the pixel program
if (program)
{
if (!CDriverD3D::compilePixelProgram(program)) return false;
CPixelProgramDrvInfosD3D *info = static_cast<CPixelProgramDrvInfosD3D *>((IProgramDrvInfos*)program->m_DrvInfo);
_PixelProgramUser = program;
setPixelShader(info->Shader);
}
else
{
setPixelShader(NULL);
_PixelProgramUser = NULL;
}
return true;
}
// ***************************************************************************
void CDriverD3D::disableHardwarePixelProgram()
{
H_AUTO_D3D(CDriverD3D_disableHardwarePixelProgram)
_DisableHardwarePixelProgram = true;
_PixelProgram = false;
}
} // NL3D

View file

@ -17,6 +17,8 @@
#include "stddirect3d.h"
#include "driver_direct3d.h"
#include "nel/misc/path.h"
#include "nel/misc/file.h"
using namespace std;
using namespace NLMISC;
@ -24,6 +26,93 @@ using namespace NLMISC;
namespace NL3D
{
// ***************************************************************************
CD3DShaderFX::~CD3DShaderFX()
{
// Must kill the drv mirror of this shader.
_DrvInfo.kill();
}
// ***************************************************************************
CD3DShaderFX::CD3DShaderFX()
{
_ShaderChanged = true;
}
// ***************************************************************************
void CD3DShaderFX::setText (const char *text)
{
_Text = text;
_ShaderChanged = true;
}
// ***************************************************************************
void CD3DShaderFX::setName (const char *name)
{
_Name = name;
_ShaderChanged = true;
}
// ***************************************************************************
bool CD3DShaderFX::loadShaderFile (const char *filename)
{
_Text = "";
// Lookup
string _filename = NLMISC::CPath::lookup(filename, false, true, true);
if (!_filename.empty())
{
// File length
uint size = NLMISC::CFile::getFileSize (_filename);
_Text.reserve (size+1);
try
{
NLMISC::CIFile file;
if (file.open (_filename))
{
// Read it
while (!file.eof ())
{
char line[512];
file.getline (line, 512);
_Text += line;
}
// Set the shader name
_Name = NLMISC::CFile::getFilename (filename);
return true;
}
else
{
nlwarning ("Can't open the file %s for reading", _filename.c_str());
}
}
catch (const Exception &e)
{
nlwarning ("Error while reading %s : %s", _filename.c_str(), e.what());
}
}
return false;
}
// ***************************************************************************
IShaderDrvInfos::~IShaderDrvInfos()
{
_Driver->removeShaderDrvInfoPtr(_DriverIterator);
}
void CDriverD3D::removeShaderDrvInfoPtr(ItShaderDrvInfoPtrList shaderIt)
{
_ShaderDrvInfos.erase(shaderIt);
}
// mem allocator for state records
std::allocator<uint8> CStateRecord::Allocator;
@ -249,7 +338,7 @@ HRESULT CDriverD3D::SetVertexShaderConstantI(UINT StartRegister, CONST INT* pCon
// ***************************************************************************
CShaderDrvInfosD3D::CShaderDrvInfosD3D(IDriver *drv, ItShaderDrvInfoPtrList it) : IShaderDrvInfos(drv, it)
CShaderDrvInfosD3D::CShaderDrvInfosD3D(CDriverD3D *drv, ItShaderDrvInfoPtrList it) : IShaderDrvInfos(drv, it)
{
H_AUTO_D3D(CShaderDrvInfosD3D_CShaderDrvInfosD3D)
Validated = false;
@ -265,7 +354,7 @@ CShaderDrvInfosD3D::~CShaderDrvInfosD3D()
// ***************************************************************************
bool CDriverD3D::validateShader(CShader *shader)
bool CDriverD3D::validateShader(CD3DShaderFX *shader)
{
H_AUTO_D3D(CDriverD3D_validateShader)
CShaderDrvInfosD3D *shaderInfo = static_cast<CShaderDrvInfosD3D*>((IShaderDrvInfos*)shader->_DrvInfo);
@ -327,7 +416,7 @@ bool CDriverD3D::validateShader(CShader *shader)
// ***************************************************************************
bool CDriverD3D::activeShader(CShader *shd)
bool CDriverD3D::activeShader(CD3DShaderFX *shd)
{
H_AUTO_D3D(CDriverD3D_activeShader)
if (_DisableHardwarePixelShader)
@ -393,7 +482,7 @@ bool CDriverD3D::activeShader(CShader *shd)
}
static void setFX(CShader &s, const char *name, const char *prog, CDriverD3D *drv)
static void setFX(CD3DShaderFX &s, const char *name, const char *prog, CDriverD3D *drv)
{
H_AUTO_D3D(setFX)

View file

@ -1187,6 +1187,11 @@ bool CDriverD3D::setRenderTarget (ITexture *tex, uint32 /* x */, uint32 /* y */,
return true;
}
ITexture *CDriverD3D::getRenderTarget() const
{
return _RenderTarget.Texture;
}
// ***************************************************************************
bool CDriverD3D::copyTargetToTexture (ITexture * /* tex */, uint32 /* offsetx */, uint32 /* offsety */, uint32 /* x */, uint32 /* y */, uint32 /* width */,

View file

@ -0,0 +1,242 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// 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 <http://www.gnu.org/licenses/>.
#include "stddirect3d.h"
#include "driver_direct3d.h"
using namespace std;
using namespace NLMISC;
namespace NL3D
{
void CDriverD3D::setUniform4f(TProgram program, uint index, float f0, float f1, float f2, float f3)
{
H_AUTO_D3D(CDriverD3D_setUniform4f);
const float tabl[4] = { f0, f1, f2, f3 };
switch (program)
{
case VertexProgram:
if (_VertexProgram)
{
setVertexProgramConstant(index, tabl);
}
break;
case PixelProgram:
if (_PixelProgram)
{
setPixelShaderConstant(index, tabl);
}
break;
}
}
void CDriverD3D::setUniform4fv(TProgram program, uint index, size_t num, const float *src)
{
H_AUTO_D3D(CDriverD3D_setUniform4fv);
switch (program)
{
case VertexProgram:
if (_VertexProgram)
{
for (uint i = 0; i < num; ++i)
{
setVertexProgramConstant(index + i, src + (i * 4));
}
}
break;
case PixelProgram:
if (_PixelProgram)
{
for (uint i = 0; i < num; ++i)
{
setPixelShaderConstant(index + i, src + (i * 4));
}
}
break;
}
}
void CDriverD3D::setUniform1f(TProgram program, uint index, float f0)
{
CDriverD3D::setUniform4f(program, index, f0, 0.f, 0.f, 0.f);
}
void CDriverD3D::setUniform2f(TProgram program, uint index, float f0, float f1)
{
CDriverD3D::setUniform4f(program, index, f0, f1, 0.f, 0.f);
}
void CDriverD3D::setUniform3f(TProgram program, uint index, float f0, float f1, float f2)
{
CDriverD3D::setUniform4f(program, index, f0, f1, f2, 0.0f);
}
void CDriverD3D::setUniform1i(TProgram program, uint index, sint32 i0)
{
}
void CDriverD3D::setUniform2i(TProgram program, uint index, sint32 i0, sint32 i1)
{
}
void CDriverD3D::setUniform3i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2)
{
}
void CDriverD3D::setUniform4i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3)
{
}
void CDriverD3D::setUniform1ui(TProgram program, uint index, uint32 ui0)
{
}
void CDriverD3D::setUniform2ui(TProgram program, uint index, uint32 ui0, uint32 ui1)
{
}
void CDriverD3D::setUniform3ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2)
{
}
void CDriverD3D::setUniform4ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3)
{
}
void CDriverD3D::setUniform3f(TProgram program, uint index, const NLMISC::CVector& v)
{
CDriverD3D::setUniform4f(program, index, v.x, v.y, v.z, 0.f);
}
void CDriverD3D::setUniform4f(TProgram program, uint index, const NLMISC::CVector& v, float f3)
{
CDriverD3D::setUniform4f(program, index, v.x, v.y, v.z, f3);
}
void CDriverD3D::setUniform4f(TProgram program, uint index, const NLMISC::CRGBAF& rgba)
{
CDriverD3D::setUniform4fv(program, index, 1, &rgba.R);
}
void CDriverD3D::setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m)
{
H_AUTO_D3D(CDriverD3D_setUniform4x4f);
// TODO: Verify this!
NLMISC::CMatrix mat = m;
mat.transpose();
const float *md = mat.get();
CDriverD3D::setUniform4fv(program, index, 4, md);
}
void CDriverD3D::setUniform4iv(TProgram program, uint index, size_t num, const sint32 *src)
{
}
void CDriverD3D::setUniform4uiv(TProgram program, uint index, size_t num, const uint32 *src)
{
}
void CDriverD3D::setUniformMatrix(NL3D::IDriver::TProgram program, uint index, NL3D::IDriver::TMatrix matrix, NL3D::IDriver::TTransform transform)
{
H_AUTO_D3D(CDriverD3D_setUniformMatrix);
D3DXMATRIX mat;
D3DXMATRIX *matPtr = NULL;
switch (matrix)
{
case IDriver::ModelView:
matPtr = &_D3DModelView;
break;
case IDriver::Projection:
matPtr = &(_MatrixCache[remapMatrixIndex(D3DTS_PROJECTION)].Matrix);
break;
case IDriver::ModelViewProjection:
matPtr = &_D3DModelViewProjection;
break;
}
if (transform != IDriver::Identity)
{
switch (transform)
{
case IDriver::Inverse:
D3DXMatrixInverse(&mat, NULL, matPtr);
break;
case IDriver::Transpose:
D3DXMatrixTranspose(&mat, matPtr);
break;
case IDriver::InverseTranspose:
D3DXMatrixInverse(&mat, NULL, matPtr);
D3DXMatrixTranspose(&mat, &mat);
break;
}
matPtr = &mat;
}
D3DXMatrixTranspose(&mat, matPtr);
CDriverD3D::setUniform4fv(program, index, 4, &mat.m[0][0]);
}
void CDriverD3D::setUniformFog(NL3D::IDriver::TProgram program, uint index)
{
H_AUTO_D3D(CDriverD3D_setUniformFog)
/* "oFog" must always be between [1, 0] what ever you set in D3DRS_FOGSTART and D3DRS_FOGEND (1 for no fog, 0 for full fog).
The Geforce4 TI 4200 (drivers 53.03 and 45.23) doesn't accept other values for "oFog". */
const float delta = _FogEnd - _FogStart;
CDriverD3D::setUniform4f(program, index,
-_D3DModelView._13 / delta,
-_D3DModelView._23 / delta,
-_D3DModelView._33 / delta,
1 - (_D3DModelView._43 - _FogStart) / delta);
}
bool CDriverD3D::setUniformDriver(TProgram program)
{
// todo
return true;
}
bool CDriverD3D::setUniformMaterial(TProgram program, CMaterial &material)
{
// todo
return true;
}
void CDriverD3D::setUniformParams(TProgram program, CGPUProgramParams &params)
{
// todo
}
} // NL3D

View file

@ -26,7 +26,7 @@ namespace NL3D
// ***************************************************************************
CVertexProgamDrvInfosD3D::CVertexProgamDrvInfosD3D(IDriver *drv, ItVtxPrgDrvInfoPtrList it) : IVertexProgramDrvInfos (drv, it)
CVertexProgamDrvInfosD3D::CVertexProgamDrvInfosD3D(IDriver *drv, ItGPUPrgDrvInfoPtrList it) : IProgramDrvInfos (drv, it)
{
H_AUTO_D3D(CVertexProgamDrvInfosD3D_CVertexProgamDrvInfosD3D)
Shader = NULL;
@ -43,10 +43,10 @@ CVertexProgamDrvInfosD3D::~CVertexProgamDrvInfosD3D()
// ***************************************************************************
bool CDriverD3D::isVertexProgramSupported () const
bool CDriverD3D::supportVertexProgram (CVertexProgram::TProfile profile) const
{
H_AUTO_D3D(CDriverD3D_isVertexProgramSupported )
return _VertexProgram;
H_AUTO_D3D(CDriverD3D_supportVertexProgram )
return (profile == CVertexProgram::nelvp) && _VertexProgram;
}
// ***************************************************************************
@ -262,101 +262,130 @@ void dump(const CVPParser::TProgram &prg, std::string &dest)
// ***************************************************************************
bool CDriverD3D::compileVertexProgram(NL3D::CVertexProgram *program)
{
// Program setuped ?
if (program->m_DrvInfo == NULL)
{
// Find nelvp
IProgram::CSource *source = NULL;
for (uint i = 0; i < program->getSourceNb(); ++i)
{
if (program->getSource(i)->Profile == CVertexProgram::nelvp)
{
source = program->getSource(i);
}
}
if (!source)
{
nlwarning("Direct3D driver only supports 'nelvp' profile, vertex program cannot be used");
return false;
}
_GPUPrgDrvInfos.push_front (NULL);
ItGPUPrgDrvInfoPtrList itTex = _GPUPrgDrvInfos.begin();
CVertexProgamDrvInfosD3D *drvInfo;
*itTex = drvInfo = new CVertexProgamDrvInfosD3D(this, itTex);
// Create a driver info structure
program->m_DrvInfo = *itTex;
/** Check with our parser if the program will works with other implemented extensions, too. (EXT_vertex_shader ..).
* There are some incompatibilities.
*/
CVPParser parser;
CVPParser::TProgram parsedProgram;
std::string errorOutput;
bool result = parser.parse(source->SourcePtr, parsedProgram, errorOutput);
if (!result)
{
nlwarning("Unable to parse a vertex program :");
nlwarning(errorOutput.c_str());
#ifdef NL_DEBUG_D3D
nlassert(0);
#endif // NL_DEBUG_D3D
return false;
}
// tmp fix for Radeon 8500/9000/9200
// Currently they hang when PaletteSkin / SkinWeight are present in the vertex declaration, but not used
// so disable them in the vertex declaration
// We don't use these component in vertex programs currently..
#ifdef NL_DEBUG
for(uint k = 0; k < parsedProgram.size(); ++k)
{
for(uint l = 0; l < parsedProgram[k].getNumUsedSrc(); ++l)
{
const CVPOperand &op = parsedProgram[k].getSrc(l);
if (op.Type == CVPOperand::InputRegister)
{
nlassert(op.Value.InputRegisterValue != CVPOperand::IWeight);
nlassert(op.Value.InputRegisterValue != CVPOperand::IPaletteSkin);
}
}
}
#endif
// Dump the vertex program
std::string dest;
dump(parsedProgram, dest);
#ifdef NL_DEBUG_D3D
nlinfo("Assemble Vertex Shader : ");
string::size_type lineBegin = 0;
string::size_type lineEnd;
while ((lineEnd = dest.find('\n', lineBegin)) != string::npos)
{
nlinfo(dest.substr (lineBegin, lineEnd-lineBegin).c_str());
lineBegin = lineEnd+1;
}
nlinfo(dest.substr (lineBegin, lineEnd-lineBegin).c_str());
#endif // NL_DEBUG_D3D
LPD3DXBUFFER pShader;
LPD3DXBUFFER pErrorMsgs;
if (D3DXAssembleShader (dest.c_str(), (UINT)dest.size(), NULL, NULL, 0, &pShader, &pErrorMsgs) == D3D_OK)
{
if (_DeviceInterface->CreateVertexShader((DWORD*)pShader->GetBufferPointer(), &(getVertexProgramD3D(*program)->Shader)) != D3D_OK)
return false;
}
else
{
nlwarning ("Can't assemble vertex program:");
nlwarning ((const char*)pErrorMsgs->GetBufferPointer());
return false;
}
// Set parameters for assembly programs
drvInfo->ParamIndices = source->ParamIndices;
// Build the feature info
program->buildInfo(source);
}
return true;
}
// ***************************************************************************
bool CDriverD3D::activeVertexProgram (CVertexProgram *program)
{
H_AUTO_D3D(CDriverD3D_activeVertexProgram )
if (_DisableHardwareVertexProgram)
return false;
// Setup or unsetup ?
if (program)
{
// Program setuped ?
if (program->_DrvInfo==NULL)
{
_VtxPrgDrvInfos.push_front (NULL);
ItVtxPrgDrvInfoPtrList itTex = _VtxPrgDrvInfos.begin();
*itTex = new CVertexProgamDrvInfosD3D(this, itTex);
// Create a driver info structure
program->_DrvInfo = *itTex;
/** Check with our parser if the program will works with other implemented extensions, too. (EXT_vertex_shader ..).
* There are some incompatibilities.
*/
CVPParser parser;
CVPParser::TProgram parsedProgram;
std::string errorOutput;
bool result = parser.parse(program->getProgram().c_str(), parsedProgram, errorOutput);
if (!result)
{
nlwarning("Unable to parse a vertex program :");
nlwarning(errorOutput.c_str());
#ifdef NL_DEBUG_D3D
nlassert(0);
#endif // NL_DEBUG_D3D
return false;
}
// tmp fix for Radeon 8500/9000/9200
// Currently they hang when PaletteSkin / SkinWeight are present in the vertex declaration, but not used
// so disable them in the vertex declaration
// We don't use these component in vertex programs currently..
#ifdef NL_DEBUG
for(uint k = 0; k < parsedProgram.size(); ++k)
{
for(uint l = 0; l < parsedProgram[k].getNumUsedSrc(); ++l)
{
const CVPOperand &op = parsedProgram[k].getSrc(l);
if (op.Type == CVPOperand::InputRegister)
{
nlassert(op.Value.InputRegisterValue != CVPOperand::IWeight);
nlassert(op.Value.InputRegisterValue != CVPOperand::IPaletteSkin);
}
}
}
#endif
// Dump the vertex program
std::string dest;
dump(parsedProgram, dest);
#ifdef NL_DEBUG_D3D
nlinfo("Assemble Vertex Shader : ");
string::size_type lineBegin = 0;
string::size_type lineEnd;
while ((lineEnd = dest.find('\n', lineBegin)) != string::npos)
{
nlinfo(dest.substr (lineBegin, lineEnd-lineBegin).c_str());
lineBegin = lineEnd+1;
}
nlinfo(dest.substr (lineBegin, lineEnd-lineBegin).c_str());
#endif // NL_DEBUG_D3D
LPD3DXBUFFER pShader;
LPD3DXBUFFER pErrorMsgs;
if (D3DXAssembleShader (dest.c_str(), (UINT)dest.size(), NULL, NULL, 0, &pShader, &pErrorMsgs) == D3D_OK)
{
if (_DeviceInterface->CreateVertexShader((DWORD*)pShader->GetBufferPointer(), &(getVertexProgramD3D(*program)->Shader)) != D3D_OK)
return false;
}
else
{
nlwarning ("Can't assemble vertex program:");
nlwarning ((const char*)pErrorMsgs->GetBufferPointer());
return false;
}
}
}
// Set the vertex program
if (program)
{
CVertexProgamDrvInfosD3D *info = static_cast<CVertexProgamDrvInfosD3D *>((IVertexProgramDrvInfos*)program->_DrvInfo);
if (!CDriverD3D::compileVertexProgram(program)) return false;
CVertexProgamDrvInfosD3D *info = NLMISC::safe_cast<CVertexProgamDrvInfosD3D *>((IProgramDrvInfos*)program->m_DrvInfo);
_VertexProgramUser = program;
setVertexProgram (info->Shader, program);
/* D3DRS_FOGSTART and D3DRS_FOGEND must be set with [1, 0] else the fog doesn't work properly on VertexShader and non-VertexShader objects
(random fog flicking) with Geforce4 TI 4200 (drivers 53.03 and 45.23). The other cards seam to interpret the "oFog"'s values using D3DRS_FOGSTART,
D3DRS_FOGEND.
Related to setUniformFog().
*/
float z = 0;
float o = 1;
@ -366,6 +395,7 @@ bool CDriverD3D::activeVertexProgram (CVertexProgram *program)
else
{
setVertexProgram (NULL, NULL);
_VertexProgramUser = NULL;
// Set the old fog range
setRenderState (D3DRS_FOGSTART, *((DWORD*) (&_FogStart)));
@ -377,171 +407,6 @@ bool CDriverD3D::activeVertexProgram (CVertexProgram *program)
// ***************************************************************************
void CDriverD3D::setConstant (uint index, float f0, float f1, float f2, float f3)
{
H_AUTO_D3D(CDriverD3D_setConstant )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
const float tabl[4] = {f0, f1, f2, f3};
setVertexProgramConstant (index, tabl);
}
// ***************************************************************************
void CDriverD3D::setConstant (uint index, double d0, double d1, double d2, double d3)
{
H_AUTO_D3D(CDriverD3D_setConstant )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
const float tabl[4] = {(float)d0, (float)d1, (float)d2, (float)d3};
setVertexProgramConstant (index, tabl);
}
// ***************************************************************************
void CDriverD3D::setConstant (uint index, const NLMISC::CVector& value)
{
H_AUTO_D3D(CDriverD3D_setConstant )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
const float tabl[4] = {value.x, value.y, value.z, 0};
setVertexProgramConstant (index, tabl);
}
// ***************************************************************************
void CDriverD3D::setConstant (uint index, const NLMISC::CVectorD& value)
{
H_AUTO_D3D(CDriverD3D_setConstant )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
const float tabl[4] = {(float)value.x, (float)value.y, (float)value.z, 0};
setVertexProgramConstant (index, tabl);
}
// ***************************************************************************
void CDriverD3D::setConstant (uint index, uint num, const float *src)
{
H_AUTO_D3D(CDriverD3D_setConstant )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
uint i;
for (i=0; i<num; i++)
setVertexProgramConstant (index+i, src+i*4);
}
// ***************************************************************************
void CDriverD3D::setConstant (uint index, uint num, const double *src)
{
H_AUTO_D3D(CDriverD3D_setConstant )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
uint i;
for (i=0; i<num; i++)
{
const float tabl[4] = {(float)src[0], (float)src[1], (float)src[2], (float)src[3]};
setVertexProgramConstant (index+i, tabl);
src += 4;
}
}
// ***************************************************************************
void CDriverD3D::setConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform)
{
H_AUTO_D3D(CDriverD3D_setConstantMatrix )
if (!_VertexProgram)
{
#ifdef NL_DEBUG
nlwarning("No vertex programs available!!");
#endif
return;
}
D3DXMATRIX mat;
D3DXMATRIX *matPtr = NULL;
switch (matrix)
{
case IDriver::ModelView:
matPtr = &_D3DModelView;
break;
case IDriver::Projection:
matPtr = &(_MatrixCache[remapMatrixIndex (D3DTS_PROJECTION)].Matrix);
break;
case IDriver::ModelViewProjection:
matPtr = &_D3DModelViewProjection;
break;
}
if (transform != IDriver::Identity)
{
mat = *matPtr;
matPtr = &mat;
switch(transform)
{
case IDriver::Inverse:
D3DXMatrixInverse (&mat, NULL, &mat);
break;
case IDriver::Transpose:
D3DXMatrixTranspose (&mat, &mat);
break;
case IDriver::InverseTranspose:
D3DXMatrixInverse (&mat, NULL, &mat);
D3DXMatrixTranspose (&mat, &mat);
break;
}
}
setConstant (index, matPtr->_11, matPtr->_21, matPtr->_31, matPtr->_41);
setConstant (index+1, matPtr->_12, matPtr->_22, matPtr->_32, matPtr->_42);
setConstant (index+2, matPtr->_13, matPtr->_23, matPtr->_33, matPtr->_43);
setConstant (index+3, matPtr->_14, matPtr->_24, matPtr->_34, matPtr->_44);
}
// ***************************************************************************
void CDriverD3D::setConstantFog (uint index)
{
H_AUTO_D3D(CDriverD3D_setConstantFog )
/* "oFog" must always be between [1, 0] what ever you set in D3DRS_FOGSTART and D3DRS_FOGEND (1 for no fog, 0 for full fog).
The Geforce4 TI 4200 (drivers 53.03 and 45.23) doesn't accept other values for "oFog". */
const float delta = _FogEnd-_FogStart;
setConstant (index, - _D3DModelView._13/delta, -_D3DModelView._23/delta, -_D3DModelView._33/delta, 1-(_D3DModelView._43-_FogStart)/delta);
}
// ***************************************************************************
void CDriverD3D::enableVertexProgramDoubleSidedColor(bool /* doubleSided */)
{
H_AUTO_D3D(CDriverD3D_enableVertexProgramDoubleSidedColor)

View file

@ -263,8 +263,6 @@ CDriverGL::CDriverGL()
_CurrentFogColor[2]= 0;
_CurrentFogColor[3]= 0;
_RenderTargetFBO = false;
_LightSetupDirty= false;
_ModelViewMatrixDirty= false;
_RenderSetupDirty= false;
@ -482,6 +480,7 @@ bool CDriverGL::setupDisplay()
}
_VertexProgramEnabled= false;
_PixelProgramEnabled= false;
_LastSetupGLArrayVertexProgram= false;
// Init VertexArrayRange according to supported extenstion.
@ -690,7 +689,7 @@ bool CDriverGL::stretchRect(ITexture * /* srcText */, NLMISC::CRect &/* srcRect
// ***************************************************************************
bool CDriverGL::supportBloomEffect() const
{
return (isVertexProgramSupported() && supportFrameBufferObject() && supportPackedDepthStencil() && supportTextureRectangle());
return (supportVertexProgram() && supportFrameBufferObject() && supportPackedDepthStencil() && supportTextureRectangle());
}
// ***************************************************************************
@ -702,7 +701,7 @@ bool CDriverGL::supportNonPowerOfTwoTextures() const
// ***************************************************************************
bool CDriverGL::isTextureRectangle(ITexture * tex) const
{
return (supportTextureRectangle() && tex->isBloomTexture() && tex->mipMapOff()
return (!supportNonPowerOfTwoTextures() && supportTextureRectangle() && tex->isBloomTexture() && tex->mipMapOff()
&& (!isPowerOf2(tex->getWidth()) || !isPowerOf2(tex->getHeight())));
}
@ -737,6 +736,12 @@ void CDriverGL::disableHardwareVertexProgram()
_Extensions.DisableHardwareVertexProgram= true;
}
void CDriverGL::disableHardwarePixelProgram()
{
H_AUTO_OGL(CDriverGL_disableHardwarePixelProgram)
_Extensions.DisableHardwarePixelProgram= true;
}
// ***************************************************************************
void CDriverGL::disableHardwareVertexArrayAGP()
{
@ -854,6 +859,7 @@ bool CDriverGL::swapBuffers()
// Reset texture shaders
//resetTextureShaders();
activeVertexProgram(NULL);
activePixelProgram(NULL);
#ifndef USE_OPENGLES
/* Yoyo: must do this (GeForce bug ??) else weird results if end render with a VBHard.
@ -1409,11 +1415,13 @@ void CDriverGL::setupFog(float start, float end, CRGBA color)
// last constant is used to store fog information (fog must be rescaled to [0, 1], because of a driver bug)
if (start != end)
{
setConstant(_EVSNumConstant, 1.f / (start - end), - end / (start - end), 0, 0);
float datas[] = { 1.f / (start - end), - end / (start - end), 0, 0 };
nglSetInvariantEXT(_EVSConstantHandle + _EVSNumConstant, GL_FLOAT, datas);
}
else
{
setConstant(_EVSNumConstant, 0.f, 0, 0, 0);
float datas[] = { 0.f, 0, 0, 0 };
nglSetInvariantEXT(_EVSConstantHandle + _EVSNumConstant, GL_FLOAT, datas);
}
}
}
@ -1535,9 +1543,9 @@ bool CDriverGL::supportTextureShaders() const
}
// ***************************************************************************
bool CDriverGL::isWaterShaderSupported() const
bool CDriverGL::supportWaterShader() const
{
H_AUTO_OGL(CDriverGL_isWaterShaderSupported);
H_AUTO_OGL(CDriverGL_supportWaterShader);
if(_Extensions.ARBFragmentProgram && ARBWaterShader[0] != 0) return true;
@ -1547,9 +1555,9 @@ bool CDriverGL::isWaterShaderSupported() const
}
// ***************************************************************************
bool CDriverGL::isTextureAddrModeSupported(CMaterial::TTexAddressingMode /* mode */) const
bool CDriverGL::supportTextureAddrMode(CMaterial::TTexAddressingMode /* mode */) const
{
H_AUTO_OGL(CDriverGL_isTextureAddrModeSupported)
H_AUTO_OGL(CDriverGL_supportTextureAddrMode)
if (_Extensions.NVTextureShader)
{
@ -1987,12 +1995,6 @@ static void fetchPerturbedEnvMapR200()
#endif
}
// ***************************************************************************
void CDriverGL::forceNativeFragmentPrograms(bool nativeOnly)
{
_ForceNativeFragmentPrograms = nativeOnly;
}
// ***************************************************************************
void CDriverGL::initFragmentShaders()
{
@ -2567,14 +2569,6 @@ CVertexBuffer::TVertexColorType CDriverGL::getVertexColorFormat() const
return CVertexBuffer::TRGBA;
}
// ***************************************************************************
bool CDriverGL::activeShader(CShader * /* shd */)
{
H_AUTO_OGL(CDriverGL_activeShader)
return false;
}
// ***************************************************************************
void CDriverGL::startBench (bool wantStandardDeviation, bool quick, bool reset)
{

View file

@ -49,7 +49,6 @@
#include "nel/3d/driver.h"
#include "nel/3d/material.h"
#include "nel/3d/shader.h"
#include "nel/3d/vertex_buffer.h"
#include "nel/3d/ptr_set.h"
#include "nel/3d/texture_cube.h"
@ -308,6 +307,7 @@ public:
virtual bool init (uint windowIcon = 0, emptyProc exitFunc = 0);
virtual void disableHardwareVertexProgram();
virtual void disableHardwarePixelProgram();
virtual void disableHardwareVertexArrayAGP();
virtual void disableHardwareTextureShader();
@ -370,8 +370,6 @@ public:
virtual void forceTextureResize(uint divisor);
virtual void forceNativeFragmentPrograms(bool nativeOnly);
/// Setup texture env functions. Used by setupMaterial
void setTextureEnvFunction(uint stage, CMaterial& mat);
@ -405,8 +403,6 @@ public:
virtual CMatrix getViewMatrix() const;
virtual bool activeShader(CShader *shd);
virtual void forceNormalize(bool normalize)
{
_ForceNormalize= normalize;
@ -565,6 +561,8 @@ public:
virtual bool setRenderTarget (ITexture *tex, uint32 x, uint32 y, uint32 width, uint32 height,
uint32 mipmapLevel, uint32 cubeFace);
virtual ITexture *getRenderTarget() const;
virtual bool copyTargetToTexture (ITexture *tex, uint32 offsetx, uint32 offsety, uint32 x, uint32 y,
uint32 width, uint32 height, uint32 mipmapLevel);
@ -602,9 +600,9 @@ public:
// @{
virtual bool supportTextureShaders() const;
virtual bool isWaterShaderSupported() const;
virtual bool supportWaterShader() const;
virtual bool isTextureAddrModeSupported(CMaterial::TTexAddressingMode mode) const;
virtual bool supportTextureAddrMode(CMaterial::TTexAddressingMode mode) const;
virtual void setMatrix2DForTextureOffsetAddrMode(const uint stage, const float mat[4]);
// @}
@ -694,6 +692,7 @@ private:
virtual class IVertexBufferHardGL *createVertexBufferHard(uint size, uint numVertices, CVertexBuffer::TPreferredMemory vbType, CVertexBuffer *vb);
friend class CTextureDrvInfosGL;
friend class CVertexProgamDrvInfosGL;
friend class CPixelProgamDrvInfosGL;
private:
// Version of the driver. Not the interface version!! Increment when implementation of the driver change.
@ -889,7 +888,7 @@ private:
// viewport before call to setRenderTarget, if BFO extension is supported
CViewport _OldViewport;
bool _RenderTargetFBO;
CSmartPtr<ITexture> _RenderTargetFBO;
// Num lights return by GL_MAX_LIGHTS
@ -1300,36 +1299,156 @@ private:
// @}
/// \name Vertex program interface
/// \name Vertex Program
// @{
bool isVertexProgramSupported () const;
bool isVertexProgramEmulated () const;
bool activeVertexProgram (CVertexProgram *program);
void setConstant (uint index, float, float, float, float);
void setConstant (uint index, double, double, double, double);
void setConstant (uint indexStart, const NLMISC::CVector& value);
void setConstant (uint indexStart, const NLMISC::CVectorD& value);
void setConstant (uint index, uint num, const float *src);
void setConstant (uint index, uint num, const double *src);
void setConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform);
void setConstantFog (uint index);
void enableVertexProgramDoubleSidedColor(bool doubleSided);
bool supportVertexProgramDoubleSidedColor() const;
// Order of preference
// - activeVertexProgram
// - CMaterial pass[n] VP (uses activeVertexProgram, but does not override if one already set by code)
// - default generic VP that mimics fixed pipeline / no VP with fixed pipeline
/**
* Does the driver supports vertex program, but emulated by CPU ?
*/
virtual bool isVertexProgramEmulated() const;
/** Return true if the driver supports the specified vertex program profile.
*/
virtual bool supportVertexProgram(CVertexProgram::TProfile profile = CVertexProgram::nelvp) const;
/** Compile the given vertex program, return if successful.
* 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);
/** Set the active vertex program. This will override vertex programs specified in CMaterial render calls.
* Also used internally by setupMaterial(CMaterial) when getVertexProgram returns NULL.
* The vertex program is activated immediately.
*/
virtual bool activeVertexProgram(CVertexProgram *program);
// @}
/// \name Pixel Program
// @{
// Order of preference
// - activePixelProgram
// - CMaterial pass[n] PP (uses activePixelProgram, but does not override if one already set by code)
// - PP generated from CMaterial (uses activePixelProgram, but does not override if one already set by code)
/** Return true if the driver supports the specified pixel program profile.
*/
virtual bool supportPixelProgram(CPixelProgram::TProfile profile = CPixelProgram::arbfp1) const;
/** Compile the given pixel program, return if successful.
* 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);
/** Set the active pixel program. This will override pixel programs specified in CMaterial render calls.
* Also used internally by setupMaterial(CMaterial) when getPixelProgram returns NULL.
* The pixel program is activated immediately.
*/
virtual bool activePixelProgram(CPixelProgram *program);
// @}
/// \name Geometry Program
// @{
// Order of preference
// - activeGeometryProgram
// - CMaterial pass[n] PP (uses activeGeometryProgram, but does not override if one already set by code)
// - none
/** Return true if the driver supports the specified pixel program profile.
*/
virtual bool supportGeometryProgram(CGeometryProgram::TProfile profile) const { return false; }
/** Compile the given pixel program, return if successful.
* 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) { return false; }
/** Set the active pixel program. This will override pixel programs specified in CMaterial render calls.
* Also used internally by setupMaterial(CMaterial) when getGeometryProgram returns NULL.
* The pixel program is activated immediately.
*/
virtual bool activeGeometryProgram(CGeometryProgram *program) { return false; }
// @}
/// \name Program parameters
// @{
// Set parameters
inline void setUniform4fInl(TProgram program, uint index, float f0, float f1, float f2, float f3);
inline void setUniform4fvInl(TProgram program, uint index, size_t num, const float *src);
virtual void setUniform1f(TProgram program, uint index, float f0);
virtual void setUniform2f(TProgram program, uint index, float f0, float f1);
virtual void setUniform3f(TProgram program, uint index, float f0, float f1, float f2);
virtual void setUniform4f(TProgram program, uint index, float f0, float f1, float f2, float f3);
virtual void setUniform1i(TProgram program, uint index, sint32 i0);
virtual void setUniform2i(TProgram program, uint index, sint32 i0, sint32 i1);
virtual void setUniform3i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2);
virtual void setUniform4i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3);
virtual void setUniform1ui(TProgram program, uint index, uint32 ui0);
virtual void setUniform2ui(TProgram program, uint index, uint32 ui0, uint32 ui1);
virtual void setUniform3ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2);
virtual void setUniform4ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3);
virtual void setUniform3f(TProgram program, uint index, const NLMISC::CVector& v);
virtual void setUniform4f(TProgram program, uint index, const NLMISC::CVector& v, float f3);
virtual void setUniform4f(TProgram program, uint index, const NLMISC::CRGBAF& rgba);
virtual void setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m);
virtual void setUniform4fv(TProgram program, uint index, size_t num, const float *src);
virtual void setUniform4iv(TProgram program, uint index, size_t num, const sint32 *src);
virtual void setUniform4uiv(TProgram program, uint index, size_t num, const uint32 *src);
// Set builtin parameters
virtual void setUniformMatrix(TProgram program, uint index, TMatrix matrix, TTransform transform);
virtual void setUniformFog(TProgram program, uint index);
// Set feature parameters
virtual bool isUniformProgramState() { return false; }
// @}
virtual void enableVertexProgramDoubleSidedColor(bool doubleSided);
virtual bool supportVertexProgramDoubleSidedColor() const;
virtual bool supportMADOperator() const ;
// @}
/// \name Vertex program implementation
// @{
bool activeNVVertexProgram (CVertexProgram *program);
bool activeARBVertexProgram (CVertexProgram *program);
bool activeEXTVertexShader (CVertexProgram *program);
bool compileNVVertexProgram (CVertexProgram *program);
bool compileARBVertexProgram (CVertexProgram *program);
bool compileEXTVertexShader (CVertexProgram *program);
//@}
/// \name Pixel program implementation
// @{
bool activeARBPixelProgram (CPixelProgram *program);
bool setupPixelProgram (CPixelProgram *program, GLuint id/*, bool &specularWritten*/);
//@}
/// \fallback for material shaders
// @{
@ -1342,15 +1461,27 @@ private:
// Don't use glIsEnabled, too slow.
return _VertexProgramEnabled;
}
bool isPixelProgramEnabled () const
{
// Don't use glIsEnabled, too slow.
return _PixelProgramEnabled;
}
// Track state of activeVertexProgram()
bool _VertexProgramEnabled;
// Track state of activePixelProgram()
bool _PixelProgramEnabled;
// Say if last setupGlArrays() was a VertexProgram setup.
bool _LastSetupGLArrayVertexProgram;
// The last vertex program that was setupped
NLMISC::CRefPtr<CVertexProgram> _LastSetuppedVP;
// The last pixel program that was setupped
NLMISC::CRefPtr<CPixelProgram> _LastSetuppedPP;
bool _ForceDXTCCompression;
/// Divisor for textureResize (power).
uint _ForceTextureResizePower;
@ -1496,7 +1627,7 @@ private:
};
// ***************************************************************************
class CVertexProgamDrvInfosGL : public IVertexProgramDrvInfos
class CVertexProgamDrvInfosGL : public IProgramDrvInfos
{
public:
// The GL Id.
@ -1517,7 +1648,36 @@ public:
// The gl id is auto created here.
CVertexProgamDrvInfosGL (CDriverGL *drv, ItVtxPrgDrvInfoPtrList it);
CVertexProgamDrvInfosGL (CDriverGL *drv, ItGPUPrgDrvInfoPtrList it);
virtual uint getUniformIndex(const char *name) const
{
std::map<std::string, uint>::const_iterator it = ParamIndices.find(name);
if (it != ParamIndices.end()) return it->second;
return ~0;
};
std::map<std::string, uint> ParamIndices;
};
// ***************************************************************************
class CPixelProgamDrvInfosGL : public IProgramDrvInfos
{
public:
// The GL Id.
GLuint ID;
// The gl id is auto created here.
CPixelProgamDrvInfosGL (CDriverGL *drv, ItGPUPrgDrvInfoPtrList it);
virtual uint getUniformIndex(const char *name) const
{
std::map<std::string, uint>::const_iterator it = ParamIndices.find(name);
if (it != ParamIndices.end()) return it->second;
return ~0;
};
std::map<std::string, uint> ParamIndices;
};
#ifdef NL_STATIC

View file

@ -1225,6 +1225,15 @@ static bool setupARBFragmentProgram(const char *glext)
return true;
}
// *********************************
static bool setupNVFragmentProgram2(const char *glext)
{
H_AUTO_OGL(setupNVFragmentProgram2);
CHECK_EXT("GL_NV_fragment_program2");
return true;
}
// ***************************************************************************
static bool setupARBVertexBufferObject(const char *glext)
{
@ -1560,6 +1569,19 @@ void registerGlExtensions(CGlExtensions &ext)
ext.EXTVertexShader = false;
ext.ARBVertexProgram = false;
}
// Check pixel program
// Disable feature ???
if (!ext.DisableHardwarePixelProgram)
{
ext.ARBFragmentProgram = setupARBFragmentProgram(glext);
ext.NVFragmentProgram2 = setupNVFragmentProgram2(glext);
}
else
{
ext.ARBFragmentProgram = false;
ext.NVFragmentProgram2 = false;
}
ext.OESDrawTexture = setupOESDrawTexture(glext);
ext.OESMapBuffer = setupOESMapBuffer(glext);
@ -1571,14 +1593,12 @@ void registerGlExtensions(CGlExtensions &ext)
ext.NVTextureShader = setupNVTextureShader(glext);
ext.ATIEnvMapBumpMap = setupATIEnvMapBumpMap(glext);
ext.ATIFragmentShader = setupATIFragmentShader(glext);
ext.ARBFragmentProgram = setupARBFragmentProgram(glext);
}
else
{
ext.ATIEnvMapBumpMap = false;
ext.NVTextureShader = false;
ext.ATIFragmentShader = false;
ext.ARBFragmentProgram = false;
}
// For now, the only way to know if emulation, is to test some extension which exist only on GeForce3.

View file

@ -103,6 +103,9 @@ struct CGlExtensions
bool ARBTextureNonPowerOfTwo;
bool ARBMultisample;
// NV Pixel Programs
bool NVFragmentProgram2;
bool OESDrawTexture;
bool OESMapBuffer;
@ -111,6 +114,7 @@ public:
/// \name Disable Hardware feature. False by default. setuped by IDriver
// @{
bool DisableHardwareVertexProgram;
bool DisableHardwarePixelProgram;
bool DisableHardwareVertexArrayAGP;
bool DisableHardwareTextureShader;
// @}
@ -174,6 +178,7 @@ public:
/// \name Disable Hardware feature. False by default. setuped by IDriver
DisableHardwareVertexProgram= false;
DisableHardwarePixelProgram= false;
DisableHardwareVertexArrayAGP= false;
DisableHardwareTextureShader= false;
}
@ -206,6 +211,7 @@ public:
result += NVTextureShader ? "NVTextureShader " : "";
result += ATIFragmentShader ? "ATIFragmentShader " : "";
result += ARBFragmentProgram ? "ARBFragmentProgram " : "";
result += NVFragmentProgram2 ? "NVFragmentProgram2 " : "";
result += ARBVertexProgram ? "ARBVertexProgram " : "";
result += NVVertexProgram ? "NVVertexProgram " : "";
result += EXTVertexShader ? "EXTVertexShader " : "";

View file

@ -283,14 +283,15 @@ void CDriverGL::setTextureShaders(const uint8 *addressingModes, const CSmartPtr<
bool CDriverGL::setupMaterial(CMaterial& mat)
{
H_AUTO_OGL(CDriverGL_setupMaterial)
CShaderGL* pShader;
GLenum glenum = GL_ZERO;
uint32 touched = mat.getTouched();
uint stage;
// profile.
_NbSetupMaterialCall++;
CMaterial::TShader matShader;
CShaderGL* pShader;
GLenum glenum = GL_ZERO;
uint32 touched = mat.getTouched();
// 0. Retrieve/Create driver shader.
//==================================
@ -359,9 +360,29 @@ bool CDriverGL::setupMaterial(CMaterial& mat)
mat.clearTouched(0xFFFFFFFF);
}
// Now we can get the supported shader from the cache.
CMaterial::TShader matShader = pShader->SupportedShader;
// 2b. User supplied pixel shader overrides material
//==================================
/*if (_VertexProgramEnabled)
{
if (!setUniformDriver(VertexProgram)) return false;
if (!setUniformMaterialInternal(VertexProgram, mat)) return false;
}*/
if (_PixelProgramEnabled)
{
matShader = CMaterial::Program;
// if (!setUniformDriver(PixelProgram)) return false;
// if (!setUniformMaterialInternal(PixelProgram, mat)) return false;
if (!_LastSetuppedPP) return false;
}
else
{
// Now we can get the supported shader from the cache.
matShader = pShader->SupportedShader;
}
// 2b. Update more shader state
//==================================
// if the shader has changed since last time
if(matShader != _CurrentMaterialSupportedShader)
{
@ -382,9 +403,11 @@ bool CDriverGL::setupMaterial(CMaterial& mat)
// Must setup textures each frame. (need to test if touched).
// Must separate texture setup and texture activation in 2 "for"...
// because setupTexture() may disable all stage.
if (matShader != CMaterial::Water)
if (matShader != CMaterial::Water
&& ((matShader != CMaterial::Program) || (_LastSetuppedPP->features().MaterialFlags & CProgramFeatures::TextureStages))
)
{
for(stage=0 ; stage<inlGetNumTextStages() ; stage++)
for (uint stage = 0; stage < inlGetNumTextStages(); ++stage)
{
ITexture *text= mat.getTexture(uint8(stage));
if (text != NULL && !setupTexture(*text))
@ -394,7 +417,7 @@ bool CDriverGL::setupMaterial(CMaterial& mat)
// Here, for Lightmap materials, setup the lightmaps.
if(matShader == CMaterial::LightMap)
{
for(stage = 0; stage < mat._LightMaps.size(); stage++)
for (uint stage = 0; stage < mat._LightMaps.size(); ++stage)
{
ITexture *text = mat._LightMaps[stage].Texture;
if (text != NULL && !setupTexture(*text))
@ -418,9 +441,10 @@ bool CDriverGL::setupMaterial(CMaterial& mat)
&& matShader != CMaterial::Cloud
&& matShader != CMaterial::Water
&& matShader != CMaterial::Specular
&& ((matShader != CMaterial::Program) || (_LastSetuppedPP->features().MaterialFlags & CProgramFeatures::TextureStages))
)
{
for(stage=0 ; stage<inlGetNumTextStages() ; stage++)
for(uint stage=0 ; stage<inlGetNumTextStages() ; stage++)
{
ITexture *text= mat.getTexture(uint8(stage));
@ -548,11 +572,13 @@ bool CDriverGL::setupMaterial(CMaterial& mat)
resetLightMapVertexSetup();
// Textures user matrix
if (matShader == CMaterial::Normal)
if (matShader == CMaterial::Normal
|| ((matShader == CMaterial::Program) && (_LastSetuppedPP->features().MaterialFlags & CProgramFeatures::TextureMatrices))
)
{
setupUserTextureMatrix(inlGetNumTextStages(), mat);
}
else // deactivate texture matrix
else
{
disableUserTextureMatrix();
}

View file

@ -0,0 +1,236 @@
/** \file driver_opengl_pixel_program.cpp
* OpenGL driver implementation for pixel program manipulation.
*
* $Id: driver_opengl_pixel_program.cpp,v 1.1.2.4 2007/07/09 15:29:00 legallo Exp $
*
* \todo manage better the init/release system (if a throw occurs in the init, we must release correctly the driver)
*/
/* Copyright, 2000 Nevrax Ltd.
*
* This file is part of NEVRAX NEL.
* NEVRAX NEL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
* NEVRAX NEL 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
* General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with NEVRAX NEL; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#include "stdopengl.h"
#include "driver_opengl.h"
#include "nel/3d/index_buffer.h"
#include "nel/3d/pixel_program.h"
#include <algorithm>
// tmp
#include "nel/misc/file.h"
using namespace std;
using namespace NLMISC;
namespace NL3D
{
#ifdef NL_STATIC
#ifdef USE_OPENGLES
namespace NLDRIVERGLES {
#else
namespace NLDRIVERGL {
#endif
#endif
// ***************************************************************************
CPixelProgamDrvInfosGL::CPixelProgamDrvInfosGL (CDriverGL *drv, ItGPUPrgDrvInfoPtrList it) : IProgramDrvInfos (drv, it)
{
H_AUTO_OGL(CPixelProgamDrvInfosGL_CPixelProgamDrvInfosGL)
// Extension must exist
nlassert(drv->_Extensions.ARBFragmentProgram);
if (drv->_Extensions.ARBFragmentProgram) // ARB implementation
{
nglGenProgramsARB(1, &ID);
}
}
// ***************************************************************************
bool CDriverGL::supportPixelProgram(CPixelProgram::TProfile profile) const
{
H_AUTO_OGL(CPixelProgamDrvInfosGL_supportPixelProgram_profile)
switch (profile)
{
case CPixelProgram::arbfp1:
return _Extensions.ARBFragmentProgram;
case CPixelProgram::fp40:
return _Extensions.NVFragmentProgram2;
}
return false;
}
// ***************************************************************************
bool CDriverGL::activePixelProgram(CPixelProgram *program)
{
H_AUTO_OGL(CDriverGL_activePixelProgram)
if (_Extensions.ARBFragmentProgram)
{
return activeARBPixelProgram(program);
}
return false;
}
// ***************************************************************************
bool CDriverGL::compilePixelProgram(NL3D::CPixelProgram *program)
{
// Program setuped ?
if (program->m_DrvInfo == NULL)
{
glDisable(GL_FRAGMENT_PROGRAM_ARB);
_PixelProgramEnabled = false;
// Insert into driver list. (so it is deleted when driver is deleted).
ItGPUPrgDrvInfoPtrList it = _GPUPrgDrvInfos.insert(_GPUPrgDrvInfos.end(), (NL3D::IProgramDrvInfos*)NULL);
// Create a driver info
CPixelProgamDrvInfosGL *drvInfo;
*it = drvInfo = new CPixelProgamDrvInfosGL(this, it);
// Set the pointer
program->m_DrvInfo = drvInfo;
if (!setupPixelProgram(program, drvInfo->ID))
{
delete drvInfo;
program->m_DrvInfo = NULL;
_GPUPrgDrvInfos.erase(it);
return false;
}
}
return true;
}
// ***************************************************************************
bool CDriverGL::activeARBPixelProgram(CPixelProgram *program)
{
H_AUTO_OGL(CDriverGL_activeARBPixelProgram)
// Setup or unsetup ?
if (program)
{
// Program setuped ?
if (!CDriverGL::compilePixelProgram(program)) return false;
// Cast the driver info pointer
CPixelProgamDrvInfosGL *drvInfo = safe_cast<CPixelProgamDrvInfosGL*>((IProgramDrvInfos*)program->m_DrvInfo);
glEnable(GL_FRAGMENT_PROGRAM_ARB);
_PixelProgramEnabled = true;
nglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, drvInfo->ID);
_LastSetuppedPP = program;
}
else
{
glDisable(GL_FRAGMENT_PROGRAM_ARB);
_PixelProgramEnabled = false;
}
return true;
}
// ***************************************************************************
bool CDriverGL::setupPixelProgram(CPixelProgram *program, GLuint id/*, bool &specularWritten*/)
{
H_AUTO_OGL(CDriverGL_setupARBPixelProgram)
CPixelProgamDrvInfosGL *drvInfo = static_cast<CPixelProgamDrvInfosGL *>((IProgramDrvInfos *)program->m_DrvInfo);
// Find a supported pixel program profile
IProgram::CSource *source = NULL;
for (uint i = 0; i < program->getSourceNb(); ++i)
{
if (supportPixelProgram(program->getSource(i)->Profile))
{
source = program->getSource(i);
}
}
if (!source)
{
nlwarning("No supported source profile for pixel program");
return false;
}
// Compile the program
nglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, id);
glGetError();
nglProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, source->SourceLen, source->SourcePtr);
GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
if (err == GL_INVALID_OPERATION)
{
GLint position;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &position);
nlassert(position != -1); // there was an error..
nlassert(position < (GLint) source->SourceLen);
uint line = 0;
const char *lineStart = source->SourcePtr;
for(uint k = 0; k < (uint) position; ++k)
{
if (source->SourcePtr[k] == '\n')
{
lineStart = source->SourcePtr + k;
++line;
}
}
nlwarning("ARB fragment program parse error at line %d.", (int) line);
// search end of line
const char *lineEnd = source->SourcePtr + source->SourceLen;
for(uint k = position; k < source->SourceLen; ++k)
{
if (source->SourcePtr[k] == '\n')
{
lineEnd = source->SourcePtr + k;
break;
}
}
nlwarning(std::string(lineStart, lineEnd).c_str());
// display the gl error msg
const GLubyte *errorMsg = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
nlassert((const char *) errorMsg);
nlwarning((const char *) errorMsg);
}
nlassert(0);
return false;
}
// Set parameters for assembly programs
drvInfo->ParamIndices = source->ParamIndices;
// Build the feature info
program->buildInfo(source);
return true;
}
#ifdef NL_STATIC
} // NLDRIVERGL/ES
#endif
} // NL3D

View file

@ -2323,7 +2323,7 @@ bool CDriverGL::setRenderTarget (ITexture *tex, uint32 x, uint32 y, uint32 width
newVP.init(0, 0, ((float)width/(float)w), ((float)height/(float)h));
setupViewport(newVP);
_RenderTargetFBO = true;
_RenderTargetFBO = tex;
return activeFrameBufferObject(tex);
}
@ -2343,7 +2343,7 @@ bool CDriverGL::setRenderTarget (ITexture *tex, uint32 x, uint32 y, uint32 width
setupViewport(_OldViewport);
_OldViewport = _CurrViewport;
_RenderTargetFBO = false;
_RenderTargetFBO = NULL;
return false;
}
@ -2356,12 +2356,17 @@ bool CDriverGL::setRenderTarget (ITexture *tex, uint32 x, uint32 y, uint32 width
// Update the scissor
setupScissor (_CurrScissor);
_RenderTargetFBO = false;
_RenderTargetFBO = NULL;
_OldViewport = _CurrViewport;
return true;
}
ITexture *CDriverGL::getRenderTarget() const
{
return _RenderTargetFBO ? _RenderTargetFBO : _TextureTarget;
}
// ***************************************************************************
bool CDriverGL::copyTargetToTexture (ITexture *tex,

View file

@ -0,0 +1,509 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// 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 <http://www.gnu.org/licenses/>.
#include "stdopengl.h"
#include "driver_opengl.h"
using namespace std;
using namespace NLMISC;
namespace NL3D {
#ifdef NL_STATIC
#ifdef USE_OPENGLES
namespace NLDRIVERGLES {
#else
namespace NLDRIVERGL {
#endif
#endif
inline void CDriverGL::setUniform4fInl(TProgram program, uint index, float f0, float f1, float f2, float f3)
{
H_AUTO_OGL(CDriverGL_setUniform4f);
#ifndef USE_OPENGLES
switch (program)
{
case VertexProgram:
if (_Extensions.NVVertexProgram)
{
// Setup constant
nglProgramParameter4fNV(GL_VERTEX_PROGRAM_NV, index, f0, f1, f2, f3);
}
else if (_Extensions.ARBVertexProgram)
{
nglProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, index, f0, f1, f2, f3);
}
else if (_Extensions.EXTVertexShader)
{
float datas[] = { f0, f1, f2, f3 };
nglSetInvariantEXT(_EVSConstantHandle + index, GL_FLOAT, datas);
}
break;
case PixelProgram:
if (_Extensions.ARBFragmentProgram)
{
nglProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, index, f0, f1, f2, f3);
}
break;
}
#endif
}
inline void CDriverGL::setUniform4fvInl(TProgram program, uint index, size_t num, const float *src)
{
H_AUTO_OGL(CDriverGL_setUniform4fv);
#ifndef USE_OPENGLES
switch (program)
{
case VertexProgram:
if (_Extensions.NVVertexProgram)
{
nglProgramParameters4fvNV(GL_VERTEX_PROGRAM_NV, index, num, src);
}
else if (_Extensions.ARBVertexProgram) // ARB pixel and geometry program will only exist when ARB vertex program exists
{
for (uint k = 0; k < num; ++k)
{
nglProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index + k, src + 4 * k);
}
}
else if (_Extensions.EXTVertexShader)
{
for (uint k = 0; k < num; ++k)
{
nglSetInvariantEXT(_EVSConstantHandle + index + k, GL_FLOAT, (void *)(src + 4 * k));
}
}
break;
case PixelProgram:
if (_Extensions.ARBFragmentProgram) // ARB pixel and geometry program will only exist when ARB vertex program exists
{
for (uint k = 0; k < num; ++k)
{
nglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index + k, src + 4 * k);
}
}
break;
}
#endif
}
void CDriverGL::setUniform1f(TProgram program, uint index, float f0)
{
CDriverGL::setUniform4fInl(program, index, f0, 0.f, 0.f, 0.f);
}
void CDriverGL::setUniform2f(TProgram program, uint index, float f0, float f1)
{
CDriverGL::setUniform4fInl(program, index, f0, f1, 0.f, 0.f);
}
void CDriverGL::setUniform3f(TProgram program, uint index, float f0, float f1, float f2)
{
CDriverGL::setUniform4fInl(program, index, f0, f1, f2, 0.0f);
}
void CDriverGL::setUniform4f(TProgram program, uint index, float f0, float f1, float f2, float f3)
{
CDriverGL::setUniform4fInl(program, index, f0, f1, f2, f3);
}
void CDriverGL::setUniform1i(TProgram program, uint index, sint32 i0)
{
}
void CDriverGL::setUniform2i(TProgram program, uint index, sint32 i0, sint32 i1)
{
}
void CDriverGL::setUniform3i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2)
{
}
void CDriverGL::setUniform4i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3)
{
}
void CDriverGL::setUniform1ui(TProgram program, uint index, uint32 ui0)
{
}
void CDriverGL::setUniform2ui(TProgram program, uint index, uint32 ui0, uint32 ui1)
{
}
void CDriverGL::setUniform3ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2)
{
}
void CDriverGL::setUniform4ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3)
{
}
void CDriverGL::setUniform3f(TProgram program, uint index, const NLMISC::CVector& v)
{
CDriverGL::setUniform4fInl(program, index, v.x, v.y, v.z, 0.f);
}
void CDriverGL::setUniform4f(TProgram program, uint index, const NLMISC::CVector& v, float f3)
{
CDriverGL::setUniform4fInl(program, index, v.x, v.y, v.z, f3);
}
void CDriverGL::setUniform4f(TProgram program, uint index, const NLMISC::CRGBAF& rgba)
{
CDriverGL::setUniform4fvInl(program, index, 1, &rgba.R);
}
void CDriverGL::setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m)
{
H_AUTO_OGL(CDriverGL_setUniform4x4f);
// TODO: Verify this!
NLMISC::CMatrix mat = m;
mat.transpose();
const float *md = mat.get();
CDriverGL::setUniform4fvInl(program, index, 4, md);
}
void CDriverGL::setUniform4fv(TProgram program, uint index, size_t num, const float *src)
{
CDriverGL::setUniform4fvInl(program, index, num, src);
}
void CDriverGL::setUniform4iv(TProgram program, uint index, size_t num, const sint32 *src)
{
}
void CDriverGL::setUniform4uiv(TProgram program, uint index, size_t num, const uint32 *src)
{
}
const uint CDriverGL::GLMatrix[IDriver::NumMatrix]=
{
GL_MODELVIEW,
GL_PROJECTION,
#ifdef USE_OPENGLES
GL_MODELVIEW
#else
GL_MODELVIEW_PROJECTION_NV
#endif
};
const uint CDriverGL::GLTransform[IDriver::NumTransform]=
{
#ifdef USE_OPENGLES
0,
0,
0,
0
#else
GL_IDENTITY_NV,
GL_INVERSE_NV,
GL_TRANSPOSE_NV,
GL_INVERSE_TRANSPOSE_NV
#endif
};
void CDriverGL::setUniformMatrix(NL3D::IDriver::TProgram program, uint index, NL3D::IDriver::TMatrix matrix, NL3D::IDriver::TTransform transform)
{
H_AUTO_OGL(CDriverGL_setUniformMatrix);
#ifndef USE_OPENGLES
// Vertex program exist ?
if (program == VertexProgram && _Extensions.NVVertexProgram)
{
// First, ensure that the render setup is correclty setuped.
refreshRenderSetup();
// Track the matrix
nglTrackMatrixNV(GL_VERTEX_PROGRAM_NV, index, GLMatrix[matrix], GLTransform[transform]);
// Release Track => matrix data is copied.
nglTrackMatrixNV(GL_VERTEX_PROGRAM_NV, index, GL_NONE, GL_IDENTITY_NV);
}
else
{
// First, ensure that the render setup is correctly setuped.
refreshRenderSetup();
CMatrix mat;
switch (matrix)
{
case IDriver::ModelView:
mat = _ModelViewMatrix;
break;
case IDriver::Projection:
{
refreshProjMatrixFromGL();
mat = _GLProjMat;
}
break;
case IDriver::ModelViewProjection:
refreshProjMatrixFromGL();
mat = _GLProjMat * _ModelViewMatrix;
break;
default:
break;
}
switch(transform)
{
case IDriver::Identity: break;
case IDriver::Inverse:
mat.invert();
break;
case IDriver::Transpose:
mat.transpose();
break;
case IDriver::InverseTranspose:
mat.invert();
mat.transpose();
break;
default:
break;
}
mat.transpose();
const float *md = mat.get();
CDriverGL::setUniform4fvInl(program, index, 4, md);
}
#endif
}
void CDriverGL::setUniformFog(NL3D::IDriver::TProgram program, uint index)
{
H_AUTO_OGL(CDriverGL_setUniformFog)
const float *values = _ModelViewMatrix.get();
CDriverGL::setUniform4fInl(program, index, -values[2], -values[6], -values[10], -values[14]);
}
/*
bool CDriverGL::setUniformDriver(TProgram program)
{
IProgram *prog = NULL;
switch (program)
{
case VertexProgram:
prog = _LastSetuppedVP;
break;
case PixelProgram:
prog = _LastSetuppedPP;
break;
}
if (!prog) return false;
const CProgramFeatures &features = prog->features();
if (features.DriverFlags)
{
if (features.DriverFlags & CProgramFeatures::Matrices)
{
if (prog->getUniformIndex(CProgramIndex::ModelView) != ~0)
{
setUniformMatrix(program, prog->getUniformIndex(CProgramIndex::ModelView), ModelView, Identity);
}
if (prog->getUniformIndex(CProgramIndex::ModelViewInverse) != ~0)
{
setUniformMatrix(program, prog->getUniformIndex(CProgramIndex::ModelViewInverse), ModelView, Inverse);
}
if (prog->getUniformIndex(CProgramIndex::ModelViewTranspose) != ~0)
{
setUniformMatrix(program, prog->getUniformIndex(CProgramIndex::ModelViewTranspose), ModelView, Transpose);
}
if (prog->getUniformIndex(CProgramIndex::ModelViewInverseTranspose) != ~0)
{
setUniformMatrix(program, prog->getUniformIndex(CProgramIndex::ModelViewInverseTranspose), ModelView, InverseTranspose);
}
if (prog->getUniformIndex(CProgramIndex::Projection) != ~0)
{
setUniformMatrix(program, prog->getUniformIndex(CProgramIndex::Projection), Projection, Identity);
}
if (prog->getUniformIndex(CProgramIndex::ProjectionInverse) != ~0)
{
setUniformMatrix(program, prog->getUniformIndex(CProgramIndex::ProjectionInverse), Projection, Inverse);
}
if (prog->getUniformIndex(CProgramIndex::ProjectionTranspose) != ~0)
{
setUniformMatrix(program, prog->getUniformIndex(CProgramIndex::ProjectionTranspose), Projection, Transpose);
}
if (prog->getUniformIndex(CProgramIndex::ProjectionInverseTranspose) != ~0)
{
setUniformMatrix(program, prog->getUniformIndex(CProgramIndex::ProjectionInverseTranspose), Projection, InverseTranspose);
}
if (prog->getUniformIndex(CProgramIndex::ModelViewProjection) != ~0)
{
setUniformMatrix(program, prog->getUniformIndex(CProgramIndex::ModelViewProjection), ModelViewProjection, Identity);
}
if (prog->getUniformIndex(CProgramIndex::ModelViewProjectionInverse) != ~0)
{
setUniformMatrix(program, prog->getUniformIndex(CProgramIndex::ModelViewProjectionInverse), ModelViewProjection, Inverse);
}
if (prog->getUniformIndex(CProgramIndex::ModelViewProjectionTranspose) != ~0)
{
setUniformMatrix(program, prog->getUniformIndex(CProgramIndex::ModelViewProjectionTranspose), ModelViewProjection, Transpose);
}
if (prog->getUniformIndex(CProgramIndex::ModelViewProjectionInverseTranspose) != ~0)
{
setUniformMatrix(program, prog->getUniformIndex(CProgramIndex::ModelViewProjectionInverseTranspose), ModelViewProjection, InverseTranspose);
}
}
if (features.DriverFlags & CProgramFeatures::Fog)
{
if (prog->getUniformIndex(CProgramIndex::Fog) != ~0)
{
setUniformFog(program, prog->getUniformIndex(CProgramIndex::Fog));
}
}
}
return true;
}
bool CDriverGL::setUniformMaterial(TProgram program, CMaterial &material)
{
IProgram *prog = NULL;
switch (program)
{
case VertexProgram:
prog = _LastSetuppedVP;
break;
case PixelProgram:
prog = _LastSetuppedPP;
break;
}
if (!prog) return false;
const CProgramFeatures &features = prog->features();
// These are also already set by setupMaterial, so setupMaterial uses setUniformMaterialInternal instead
if (features.MaterialFlags & (CProgramFeatures::TextureStages | CProgramFeatures::TextureMatrices))
{
if (features.MaterialFlags & CProgramFeatures::TextureStages)
{
for (uint stage = 0; stage < inlGetNumTextStages(); ++stage)
{
ITexture *text= material.getTexture(uint8(stage));
// Must setup textures each frame. (need to test if touched).
if (text != NULL && !setupTexture(*text))
return false;
// activate the texture, or disable texturing if NULL.
activateTexture(stage, text);
// If texture not NULL, Change texture env function.
setTextureEnvFunction(stage, material);
}
}
if (features.MaterialFlags & CProgramFeatures::TextureMatrices)
{
// Textures user matrix
setupUserTextureMatrix(inlGetNumTextStages(), material);
}
}
return true;
}
bool CDriverGL::setUniformMaterialInternal(TProgram program, CMaterial &material)
{
IProgram *prog = NULL;
switch (program)
{
case VertexProgram:
prog = _LastSetuppedVP;
break;
case PixelProgram:
prog = _LastSetuppedPP;
break;
}
if (!prog) return false;
const CProgramFeatures &features = prog->features();
if (features.MaterialFlags & ~(CProgramFeatures::TextureStages | CProgramFeatures::TextureMatrices))
{
// none
}
return true;
}
void CDriverGL::setUniformParams(TProgram program, CGPUProgramParams &params)
{
IProgram *prog = NULL;
switch (program)
{
case VertexProgram:
prog = _LastSetuppedVP;
break;
case PixelProgram:
prog = _LastSetuppedPP;
break;
}
if (!prog) return;
size_t offset = params.getBegin();
while (offset != params.getEnd())
{
uint size = params.getSizeByOffset(offset);
uint count = params.getCountByOffset(offset);
nlassert(size == 4 || count == 1); // only support float4 arrays
nlassert(params.getTypeByOffset(offset) == CGPUProgramParams::Float); // only support float
uint index = params.getIndexByOffset(offset);
if (index == ~0)
{
const std::string &name = params.getNameByOffset(offset);
nlassert(!name.empty() /* missing both parameter name and index, code error /);
uint index = prog->getUniformIndex(name.c_str());
nlassert(index != ~0 /* invalid parameter name /);
params.map(index, name);
}
setUniform4fv(program, index, count, params.getPtrFByOffset(offset));
offset = params.getNext(offset);
}
}
*/
#ifdef NL_STATIC
} // NLDRIVERGL/ES
#endif
} // NL3D

View file

@ -1151,7 +1151,7 @@ void CDriverGL::toggleGlArraysForEXTVertexShader()
CVertexProgram *vp = _LastSetuppedVP;
if (vp)
{
CVertexProgamDrvInfosGL *drvInfo = NLMISC::safe_cast<CVertexProgamDrvInfosGL *>((IVertexProgramDrvInfos *) vp->_DrvInfo);
CVertexProgamDrvInfosGL *drvInfo = NLMISC::safe_cast<CVertexProgamDrvInfosGL *>((IProgramDrvInfos *) vp->m_DrvInfo);
if (drvInfo)
{
// Disable all VertexAttribs.
@ -1396,7 +1396,7 @@ void CDriverGL::setupGlArraysForEXTVertexShader(CVertexBufferInfo &vb)
CVertexProgram *vp = _LastSetuppedVP;
if (!vp) return;
CVertexProgamDrvInfosGL *drvInfo = NLMISC::safe_cast<CVertexProgamDrvInfosGL *>((IVertexProgramDrvInfos *) vp->_DrvInfo);
CVertexProgamDrvInfosGL *drvInfo = NLMISC::safe_cast<CVertexProgamDrvInfosGL *>((IProgramDrvInfos *) vp->m_DrvInfo);
if (!drvInfo) return;
uint32 flags= vb.VertexFormat;

View file

@ -41,7 +41,7 @@ namespace NLDRIVERGL {
#endif
// ***************************************************************************
CVertexProgamDrvInfosGL::CVertexProgamDrvInfosGL (CDriverGL *drv, ItVtxPrgDrvInfoPtrList it) : IVertexProgramDrvInfos (drv, it)
CVertexProgamDrvInfosGL::CVertexProgamDrvInfosGL(CDriverGL *drv, ItGPUPrgDrvInfoPtrList it) : IProgramDrvInfos (drv, it)
{
H_AUTO_OGL(CVertexProgamDrvInfosGL_CVertexProgamDrvInfosGL);
@ -70,23 +70,136 @@ CVertexProgamDrvInfosGL::CVertexProgamDrvInfosGL (CDriverGL *drv, ItVtxPrgDrvInf
// ***************************************************************************
bool CDriverGL::isVertexProgramSupported () const
bool CDriverGL::supportVertexProgram(CVertexProgram::TProfile profile) const
{
H_AUTO_OGL(CVertexProgamDrvInfosGL_isVertexProgramSupported)
return _Extensions.NVVertexProgram || _Extensions.EXTVertexShader || _Extensions.ARBVertexProgram;
H_AUTO_OGL(CVertexProgamDrvInfosGL_supportVertexProgram)
return (profile == CVertexProgram::nelvp)
&& (_Extensions.NVVertexProgram || _Extensions.EXTVertexShader || _Extensions.ARBVertexProgram);
}
// ***************************************************************************
bool CDriverGL::isVertexProgramEmulated () const
bool CDriverGL::isVertexProgramEmulated() const
{
H_AUTO_OGL(CVertexProgamDrvInfosGL_isVertexProgramEmulated)
return _Extensions.NVVertexProgramEmulated;
}
bool CDriverGL::compileNVVertexProgram(CVertexProgram *program)
{
H_AUTO_OGL(CDriverGL_compileNVVertexProgram);
#ifndef USE_OPENGLES
// Driver info
CVertexProgamDrvInfosGL *drvInfo;
nlassert(!program->m_DrvInfo);
glDisable(GL_VERTEX_PROGRAM_NV);
_VertexProgramEnabled = false;
// Find nelvp
IProgram::CSource *source = NULL;
for (uint i = 0; i < program->getSourceNb(); ++i)
{
if (program->getSource(i)->Profile == CVertexProgram::nelvp)
{
source = program->getSource(i);
}
}
if (!source)
{
nlwarning("OpenGL driver only supports 'nelvp' profile, vertex program cannot be used");
return false;
}
/** Check with our parser if the program will works with other implemented extensions, too. (EXT_vertex_shader ..).
* There are some incompatibilities.
*/
CVPParser parser;
CVPParser::TProgram parsedProgram;
std::string errorOutput;
bool result = parser.parse(source->SourcePtr, parsedProgram, errorOutput);
if (!result)
{
nlwarning("Unable to parse a vertex program :");
nlwarning(errorOutput.c_str());
#ifdef NL_DEBUG
nlassert(0);
#endif
return false;
}
// Insert into driver list. (so it is deleted when driver is deleted).
ItGPUPrgDrvInfoPtrList it = _GPUPrgDrvInfos.insert(_GPUPrgDrvInfos.end(), (NL3D::IProgramDrvInfos*)NULL);
// Create a driver info
*it = drvInfo = new CVertexProgamDrvInfosGL(this, it);
// Set the pointer
program->m_DrvInfo = drvInfo;
// Compile the program
nglLoadProgramNV(GL_VERTEX_PROGRAM_NV, drvInfo->ID, (GLsizei)source->SourceLen, (const GLubyte*)source->SourcePtr);
// Get loading error code
GLint errorOff;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_NV, &errorOff);
// Compilation error ?
if (errorOff >= 0)
{
// String length
uint length = (uint)source->SourceLen;
const char* sString = source->SourcePtr;
// Line count and char count
uint line=1;
uint charC=1;
// Find the line
uint offset=0;
while ((offset < length) && (offset < (uint)errorOff))
{
if (sString[offset]=='\n')
{
line++;
charC=1;
}
else
charC++;
// Next character
offset++;
}
// Show the error
nlwarning("3D: Vertex program syntax error line %d character %d\n", line, charC);
// Setup not ok
delete drvInfo;
program->m_DrvInfo = NULL;
_GPUPrgDrvInfos.erase(it);
return false;
}
// Set parameters for assembly programs
drvInfo->ParamIndices = source->ParamIndices;
// Build the feature info
program->buildInfo(source);
// Setup ok
return true;
#else
return false;
#endif
}
// ***************************************************************************
bool CDriverGL::activeNVVertexProgram (CVertexProgram *program)
bool CDriverGL::activeNVVertexProgram(CVertexProgram *program)
{
H_AUTO_OGL(CVertexProgamDrvInfosGL_activeNVVertexProgram);
@ -94,99 +207,16 @@ bool CDriverGL::activeNVVertexProgram (CVertexProgram *program)
// Setup or unsetup ?
if (program)
{
// Enable vertex program
glEnable (GL_VERTEX_PROGRAM_NV);
_VertexProgramEnabled= true;
// Driver info
CVertexProgamDrvInfosGL *drvInfo;
CVertexProgamDrvInfosGL *drvInfo = safe_cast<CVertexProgamDrvInfosGL*>((IProgramDrvInfos*)program->m_DrvInfo);
nlassert(drvInfo);
// Program setuped ?
if (program->_DrvInfo==NULL)
{
/** Check with our parser if the program will works with other implemented extensions, too. (EXT_vertex_shader ..).
* There are some incompatibilities.
*/
CVPParser parser;
CVPParser::TProgram parsedProgram;
std::string errorOutput;
bool result = parser.parse(program->getProgram().c_str(), parsedProgram, errorOutput);
if (!result)
{
nlwarning("Unable to parse a vertex program :");
nlwarning(errorOutput.c_str());
#ifdef NL_DEBUG
nlassert(0);
#endif
return false;
}
// Insert into driver list. (so it is deleted when driver is deleted).
ItVtxPrgDrvInfoPtrList it= _VtxPrgDrvInfos.insert(_VtxPrgDrvInfos.end(), (NL3D::IVertexProgramDrvInfos*)NULL);
// Create a driver info
*it = drvInfo = new CVertexProgamDrvInfosGL (this, it);
// Set the pointer
program->_DrvInfo=drvInfo;
// Compile the program
nglLoadProgramNV (GL_VERTEX_PROGRAM_NV, drvInfo->ID, (GLsizei)program->getProgram().length(), (const GLubyte*)program->getProgram().c_str());
// Get loading error code
GLint errorOff;
glGetIntegerv (GL_PROGRAM_ERROR_POSITION_NV, &errorOff);
// Compilation error ?
if (errorOff>=0)
{
// String length
uint length = (uint)program->getProgram ().length();
const char* sString= program->getProgram ().c_str();
// Line count and char count
uint line=1;
uint charC=1;
// Find the line
uint offset=0;
while ((offset<length)&&(offset<(uint)errorOff))
{
if (sString[offset]=='\n')
{
line++;
charC=1;
}
else
charC++;
// Next character
offset++;
}
// Show the error
nlwarning("3D: Vertex program syntax error line %d character %d\n", line, charC);
// Disable vertex program
glDisable (GL_VERTEX_PROGRAM_NV);
_VertexProgramEnabled= false;
// Setup not ok
return false;
}
// Setup ok
return true;
}
else
{
// Cast the driver info pointer
drvInfo=safe_cast<CVertexProgamDrvInfosGL*>((IVertexProgramDrvInfos*)program->_DrvInfo);
}
// Enable vertex program
glEnable(GL_VERTEX_PROGRAM_NV);
_VertexProgramEnabled = true;
// Setup this program
nglBindProgramNV (GL_VERTEX_PROGRAM_NV, drvInfo->ID);
nglBindProgramNV(GL_VERTEX_PROGRAM_NV, drvInfo->ID);
_LastSetuppedVP = program;
// Ok
@ -195,8 +225,8 @@ bool CDriverGL::activeNVVertexProgram (CVertexProgram *program)
else // Unsetup
{
// Disable vertex program
glDisable (GL_VERTEX_PROGRAM_NV);
_VertexProgramEnabled= false;
glDisable(GL_VERTEX_PROGRAM_NV);
_VertexProgramEnabled = false;
// Ok
return true;
}
@ -1486,165 +1516,273 @@ bool CDriverGL::setupARBVertexProgram (const CVPParser::TProgram &inParsedProgra
#endif
}
// ***************************************************************************
bool CDriverGL::compileARBVertexProgram(NL3D::CVertexProgram *program)
{
H_AUTO_OGL(CDriverGL_compileARBVertexProgram);
#ifndef USE_OPENGLES
nlassert(!program->m_DrvInfo);
glDisable(GL_VERTEX_PROGRAM_ARB);
_VertexProgramEnabled = false;
// Find nelvp
IProgram::CSource *source = NULL;
for (uint i = 0; i < program->getSourceNb(); ++i)
{
if (program->getSource(i)->Profile == CVertexProgram::nelvp)
{
source = program->getSource(i);
}
}
if (!source)
{
nlwarning("OpenGL driver only supports 'nelvp' profile, vertex program cannot be used");
return false;
}
// try to parse the program
CVPParser parser;
CVPParser::TProgram parsedProgram;
std::string errorOutput;
bool result = parser.parse(source->SourcePtr, parsedProgram, errorOutput);
if (!result)
{
nlwarning("Unable to parse a vertex program.");
#ifdef NL_DEBUG
nlerror(errorOutput.c_str());
#endif
return false;
}
// Insert into driver list. (so it is deleted when driver is deleted).
ItGPUPrgDrvInfoPtrList it = _GPUPrgDrvInfos.insert(_GPUPrgDrvInfos.end(), (NL3D::IProgramDrvInfos*)NULL);
// Create a driver info
CVertexProgamDrvInfosGL *drvInfo;
*it = drvInfo = new CVertexProgamDrvInfosGL(this, it);
// Set the pointer
program->m_DrvInfo = drvInfo;
if (!setupARBVertexProgram(parsedProgram, drvInfo->ID, drvInfo->SpecularWritten))
{
delete drvInfo;
program->m_DrvInfo = NULL;
_GPUPrgDrvInfos.erase(it);
return false;
}
// Set parameters for assembly programs
drvInfo->ParamIndices = source->ParamIndices;
// Build the feature info
program->buildInfo(source);
return true;
#else
return false;
#endif
}
// ***************************************************************************
bool CDriverGL::activeARBVertexProgram (CVertexProgram *program)
bool CDriverGL::activeARBVertexProgram(CVertexProgram *program)
{
H_AUTO_OGL(CDriverGL_activeARBVertexProgram);
#ifndef USE_OPENGLES
// Setup or unsetup ?
if (program)
{
// Driver info
CVertexProgamDrvInfosGL *drvInfo;
CVertexProgamDrvInfosGL *drvInfo = safe_cast<CVertexProgamDrvInfosGL*>((IProgramDrvInfos*)program->m_DrvInfo);
nlassert(drvInfo);
// Program setuped ?
if (program->_DrvInfo==NULL)
{
// try to parse the program
CVPParser parser;
CVPParser::TProgram parsedProgram;
std::string errorOutput;
bool result = parser.parse(program->getProgram().c_str(), parsedProgram, errorOutput);
if (!result)
{
nlwarning("Unable to parse a vertex program.");
#ifdef NL_DEBUG
nlerror(errorOutput.c_str());
#endif
return false;
}
// Insert into driver list. (so it is deleted when driver is deleted).
ItVtxPrgDrvInfoPtrList it= _VtxPrgDrvInfos.insert(_VtxPrgDrvInfos.end(), (NL3D::IVertexProgramDrvInfos*)NULL);
// Create a driver info
*it = drvInfo = new CVertexProgamDrvInfosGL (this, it);
// Set the pointer
program->_DrvInfo=drvInfo;
if (!setupARBVertexProgram(parsedProgram, drvInfo->ID, drvInfo->SpecularWritten))
{
delete drvInfo;
program->_DrvInfo = NULL;
_VtxPrgDrvInfos.erase(it);
return false;
}
}
else
{
// Cast the driver info pointer
drvInfo=safe_cast<CVertexProgamDrvInfosGL*>((IVertexProgramDrvInfos*)program->_DrvInfo);
}
glEnable( GL_VERTEX_PROGRAM_ARB );
_VertexProgramEnabled = true;
nglBindProgramARB( GL_VERTEX_PROGRAM_ARB, drvInfo->ID );
nglBindProgramARB(GL_VERTEX_PROGRAM_ARB, drvInfo->ID);
if (drvInfo->SpecularWritten)
{
glEnable( GL_COLOR_SUM_ARB );
glEnable(GL_COLOR_SUM_ARB);
}
else
{
glDisable( GL_COLOR_SUM_ARB ); // no specular written
glDisable(GL_COLOR_SUM_ARB); // no specular written
}
_LastSetuppedVP = program;
}
else
{
glDisable( GL_VERTEX_PROGRAM_ARB );
glDisable( GL_COLOR_SUM_ARB );
glDisable(GL_VERTEX_PROGRAM_ARB);
glDisable(GL_COLOR_SUM_ARB);
_VertexProgramEnabled = false;
}
return true;
#else
return false;
#endif
}
// ***************************************************************************
bool CDriverGL::activeEXTVertexShader (CVertexProgram *program)
bool CDriverGL::compileEXTVertexShader(CVertexProgram *program)
{
H_AUTO_OGL(CDriverGL_activeEXTVertexShader);
#ifndef USE_OPENGLES
// Setup or unsetup ?
if (program)
nlassert(program->m_DrvInfo);
glDisable(GL_VERTEX_SHADER_EXT);
_VertexProgramEnabled = false;
// Find nelvp
IProgram::CSource *source = NULL;
for (uint i = 0; i < program->getSourceNb(); ++i)
{
// Driver info
CVertexProgamDrvInfosGL *drvInfo;
// Program setuped ?
if (program->_DrvInfo==NULL)
if (program->getSource(i)->Profile == CVertexProgram::nelvp)
{
// try to parse the program
CVPParser parser;
CVPParser::TProgram parsedProgram;
std::string errorOutput;
bool result = parser.parse(program->getProgram().c_str(), parsedProgram, errorOutput);
if (!result)
{
nlwarning("Unable to parse a vertex program.");
#ifdef NL_DEBUG
nlerror(errorOutput.c_str());
#endif
return false;
}
/*
FILE *f = fopen(getLogDirectory() + "test.txt", "wb");
if (f)
{
std::string vpText;
CVPParser::dump(parsedProgram, vpText);
fwrite(vpText.c_str(), vpText.size(), 1, f);
fclose(f);
}
*/
// Insert into driver list. (so it is deleted when driver is deleted).
ItVtxPrgDrvInfoPtrList it= _VtxPrgDrvInfos.insert(_VtxPrgDrvInfos.end(), (NL3D::IVertexProgramDrvInfos*)NULL);
// Create a driver info
*it = drvInfo = new CVertexProgamDrvInfosGL (this, it);
// Set the pointer
program->_DrvInfo=drvInfo;
if (!setupEXTVertexShader(parsedProgram, drvInfo->ID, drvInfo->Variants, drvInfo->UsedVertexComponents))
{
delete drvInfo;
program->_DrvInfo = NULL;
_VtxPrgDrvInfos.erase(it);
return false;
}
source = program->getSource(i);
}
else
{
// Cast the driver info pointer
drvInfo=safe_cast<CVertexProgamDrvInfosGL*>((IVertexProgramDrvInfos*)program->_DrvInfo);
}
glEnable( GL_VERTEX_SHADER_EXT);
_VertexProgramEnabled = true;
nglBindVertexShaderEXT( drvInfo->ID );
_LastSetuppedVP = program;
}
else
if (!source)
{
glDisable( GL_VERTEX_SHADER_EXT );
_VertexProgramEnabled = false;
nlwarning("OpenGL driver only supports 'nelvp' profile, vertex program cannot be used");
return false;
}
// try to parse the program
CVPParser parser;
CVPParser::TProgram parsedProgram;
std::string errorOutput;
bool result = parser.parse(source->SourcePtr, parsedProgram, errorOutput);
if (!result)
{
nlwarning("Unable to parse a vertex program.");
#ifdef NL_DEBUG
nlerror(errorOutput.c_str());
#endif
return false;
}
/*
FILE *f = fopen(getLogDirectory() + "test.txt", "wb");
if (f)
{
std::string vpText;
CVPParser::dump(parsedProgram, vpText);
fwrite(vpText.c_str(), vpText.size(), 1, f);
fclose(f);
}
*/
// Insert into driver list. (so it is deleted when driver is deleted).
ItGPUPrgDrvInfoPtrList it= _GPUPrgDrvInfos.insert(_GPUPrgDrvInfos.end(), (NL3D::IProgramDrvInfos*)NULL);
// Create a driver info
CVertexProgamDrvInfosGL *drvInfo;
*it = drvInfo = new CVertexProgamDrvInfosGL (this, it);
// Set the pointer
program->m_DrvInfo=drvInfo;
if (!setupEXTVertexShader(parsedProgram, drvInfo->ID, drvInfo->Variants, drvInfo->UsedVertexComponents))
{
delete drvInfo;
program->m_DrvInfo = NULL;
_GPUPrgDrvInfos.erase(it);
return false;
}
// Set parameters for assembly programs
drvInfo->ParamIndices = source->ParamIndices;
// Build the feature info
program->buildInfo(source);
return true;
#else
return false;
#endif
}
// ***************************************************************************
bool CDriverGL::activeVertexProgram (CVertexProgram *program)
bool CDriverGL::activeEXTVertexShader(CVertexProgram *program)
{
H_AUTO_OGL(CDriverGL_activeEXTVertexShader);
#ifndef USE_OPENGLES
// Setup or unsetup ?
if (program)
{
// Driver info
CVertexProgamDrvInfosGL *drvInfo = safe_cast<CVertexProgamDrvInfosGL*>((IProgramDrvInfos*)program->m_DrvInfo);
nlassert(drvInfo);
glEnable(GL_VERTEX_SHADER_EXT);
_VertexProgramEnabled = true;
nglBindVertexShaderEXT(drvInfo->ID);
_LastSetuppedVP = program;
}
else
{
glDisable(GL_VERTEX_SHADER_EXT);
_VertexProgramEnabled = false;
}
return true;
#else
return false;
#endif
}
bool CDriverGL::compileVertexProgram(NL3D::CVertexProgram *program)
{
if (program->m_DrvInfo == NULL)
{
// Extension
if (_Extensions.NVVertexProgram)
{
return compileNVVertexProgram(program);
}
else if (_Extensions.ARBVertexProgram)
{
return compileARBVertexProgram(program);
}
else if (_Extensions.EXTVertexShader)
{
return compileEXTVertexShader(program);
}
// Can't do anything
return false;
}
return true;
}
// ***************************************************************************
bool CDriverGL::activeVertexProgram(CVertexProgram *program)
{
H_AUTO_OGL(CDriverGL_activeVertexProgram)
// Extension here ?
// Compile if necessary
if (program && !CDriverGL::compileVertexProgram(program)) return false;
// Extension
if (_Extensions.NVVertexProgram)
{
return activeNVVertexProgram(program);
@ -1662,287 +1800,6 @@ bool CDriverGL::activeVertexProgram (CVertexProgram *program)
return false;
}
// ***************************************************************************
void CDriverGL::setConstant (uint index, float f0, float f1, float f2, float f3)
{
H_AUTO_OGL(CDriverGL_setConstant);
#ifndef USE_OPENGLES
// Vertex program exist ?
if (_Extensions.NVVertexProgram)
{
// Setup constant
nglProgramParameter4fNV (GL_VERTEX_PROGRAM_NV, index, f0, f1, f2, f3);
}
else if (_Extensions.ARBVertexProgram)
{
nglProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, index, f0, f1, f2, f3);
}
else if (_Extensions.EXTVertexShader)
{
float datas[] = { f0, f1, f2, f3 };
nglSetInvariantEXT(_EVSConstantHandle + index, GL_FLOAT, datas);
}
#endif
}
// ***************************************************************************
void CDriverGL::setConstant (uint index, double d0, double d1, double d2, double d3)
{
H_AUTO_OGL(CDriverGL_setConstant);
#ifndef USE_OPENGLES
// Vertex program exist ?
if (_Extensions.NVVertexProgram)
{
// Setup constant
nglProgramParameter4dNV (GL_VERTEX_PROGRAM_NV, index, d0, d1, d2, d3);
}
else if (_Extensions.ARBVertexProgram)
{
nglProgramEnvParameter4dARB(GL_VERTEX_PROGRAM_ARB, index, d0, d1, d2, d3);
}
else if (_Extensions.EXTVertexShader)
{
double datas[] = { d0, d1, d2, d3 };
nglSetInvariantEXT(_EVSConstantHandle + index, GL_DOUBLE, datas);
}
#endif
}
// ***************************************************************************
void CDriverGL::setConstant (uint index, const NLMISC::CVector& value)
{
H_AUTO_OGL(CDriverGL_setConstant);
#ifndef USE_OPENGLES
// Vertex program exist ?
if (_Extensions.NVVertexProgram)
{
// Setup constant
nglProgramParameter4fNV (GL_VERTEX_PROGRAM_NV, index, value.x, value.y, value.z, 0);
}
else if (_Extensions.ARBVertexProgram)
{
nglProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, index, value.x, value.y, value.z, 0);
}
else if (_Extensions.EXTVertexShader)
{
float datas[] = { value.x, value.y, value.z, 0 };
nglSetInvariantEXT(_EVSConstantHandle + index, GL_FLOAT, datas);
}
#endif
}
// ***************************************************************************
void CDriverGL::setConstant (uint index, const NLMISC::CVectorD& value)
{
H_AUTO_OGL(CDriverGL_setConstant);
#ifndef USE_OPENGLES
// Vertex program exist ?
if (_Extensions.NVVertexProgram)
{
// Setup constant
nglProgramParameter4dNV (GL_VERTEX_PROGRAM_NV, index, value.x, value.y, value.z, 0);
}
else if (_Extensions.ARBVertexProgram)
{
nglProgramEnvParameter4dARB(GL_VERTEX_PROGRAM_ARB, index, value.x, value.y, value.z, 0);
}
else if (_Extensions.EXTVertexShader)
{
double datas[] = { value.x, value.y, value.z, 0 };
nglSetInvariantEXT(_EVSConstantHandle + index, GL_DOUBLE, datas);
}
#endif
}
// ***************************************************************************
void CDriverGL::setConstant (uint index, uint num, const float *src)
{
H_AUTO_OGL(CDriverGL_setConstant);
#ifndef USE_OPENGLES
// Vertex program exist ?
if (_Extensions.NVVertexProgram)
{
nglProgramParameters4fvNV(GL_VERTEX_PROGRAM_NV, index, num, src);
}
else if (_Extensions.ARBVertexProgram)
{
for(uint k = 0; k < num; ++k)
{
nglProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index + k, src + 4 * k);
}
}
else if (_Extensions.EXTVertexShader)
{
for(uint k = 0; k < num; ++k)
{
nglSetInvariantEXT(_EVSConstantHandle + index + k, GL_FLOAT, (void *) (src + 4 * k));
}
}
#endif
}
// ***************************************************************************
void CDriverGL::setConstant (uint index, uint num, const double *src)
{
H_AUTO_OGL(CDriverGL_setConstant);
#ifndef USE_OPENGLES
// Vertex program exist ?
if (_Extensions.NVVertexProgram)
{
nglProgramParameters4dvNV(GL_VERTEX_PROGRAM_NV, index, num, src);
}
else if (_Extensions.ARBVertexProgram)
{
for(uint k = 0; k < num; ++k)
{
nglProgramEnvParameter4dvARB(GL_VERTEX_PROGRAM_ARB, index + k, src + 4 * k);
}
}
else if (_Extensions.EXTVertexShader)
{
for(uint k = 0; k < num; ++k)
{
nglSetInvariantEXT(_EVSConstantHandle + index + k, GL_DOUBLE, (void *) (src + 4 * k));
}
}
#endif
}
// ***************************************************************************
const uint CDriverGL::GLMatrix[IDriver::NumMatrix]=
{
GL_MODELVIEW,
GL_PROJECTION,
#ifdef USE_OPENGLES
GL_MODELVIEW
#else
GL_MODELVIEW_PROJECTION_NV
#endif
};
// ***************************************************************************
const uint CDriverGL::GLTransform[IDriver::NumTransform]=
{
#ifdef USE_OPENGLES
0,
0,
0,
0
#else
GL_IDENTITY_NV,
GL_INVERSE_NV,
GL_TRANSPOSE_NV,
GL_INVERSE_TRANSPOSE_NV
#endif
};
// ***************************************************************************
void CDriverGL::setConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform)
{
H_AUTO_OGL(CDriverGL_setConstantMatrix);
#ifndef USE_OPENGLES
// Vertex program exist ?
if (_Extensions.NVVertexProgram)
{
// First, ensure that the render setup is correclty setuped.
refreshRenderSetup();
// Track the matrix
nglTrackMatrixNV (GL_VERTEX_PROGRAM_NV, index, GLMatrix[matrix], GLTransform[transform]);
// Release Track => matrix data is copied.
nglTrackMatrixNV (GL_VERTEX_PROGRAM_NV, index, GL_NONE, GL_IDENTITY_NV);
}
else
{
// First, ensure that the render setup is correctly setuped.
refreshRenderSetup();
CMatrix mat;
switch (matrix)
{
case IDriver::ModelView:
mat = _ModelViewMatrix;
break;
case IDriver::Projection:
{
refreshProjMatrixFromGL();
mat = _GLProjMat;
}
break;
case IDriver::ModelViewProjection:
refreshProjMatrixFromGL();
mat = _GLProjMat * _ModelViewMatrix;
break;
default:
break;
}
switch(transform)
{
case IDriver::Identity: break;
case IDriver::Inverse:
mat.invert();
break;
case IDriver::Transpose:
mat.transpose();
break;
case IDriver::InverseTranspose:
mat.invert();
mat.transpose();
break;
default:
break;
}
mat.transpose();
float matDatas[16];
mat.get(matDatas);
if (_Extensions.ARBVertexProgram)
{
nglProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, matDatas);
nglProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index + 1, matDatas + 4);
nglProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index + 2, matDatas + 8);
nglProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index + 3, matDatas + 12);
}
else
{
nglSetInvariantEXT(_EVSConstantHandle + index, GL_FLOAT, matDatas);
nglSetInvariantEXT(_EVSConstantHandle + index + 1, GL_FLOAT, matDatas + 4);
nglSetInvariantEXT(_EVSConstantHandle + index + 2, GL_FLOAT, matDatas + 8);
nglSetInvariantEXT(_EVSConstantHandle + index + 3, GL_FLOAT, matDatas + 12);
}
}
#endif
}
// ***************************************************************************
void CDriverGL::setConstantFog (uint index)
{
H_AUTO_OGL(CDriverGL_setConstantFog)
const float *values = _ModelViewMatrix.get();
setConstant (index, -values[2], -values[6], -values[10], -values[14]);
}
// ***************************************************************************
void CDriverGL::enableVertexProgramDoubleSidedColor(bool doubleSided)

View file

@ -213,6 +213,12 @@ void CDriverUser::disableHardwareVertexProgram()
_Driver->disableHardwareVertexProgram();
}
void CDriverUser::disableHardwarePixelProgram()
{
NL3D_HAUTO_UI_DRIVER;
_Driver->disableHardwarePixelProgram();
}
void CDriverUser::disableHardwareVertexArrayAGP()
{
NL3D_HAUTO_UI_DRIVER;
@ -1490,12 +1496,6 @@ void CDriverUser::forceTextureResize(uint divisor)
_Driver->forceTextureResize(divisor);
}
void CDriverUser::forceNativeFragmentPrograms(bool nativeOnly)
{
NL3D_HAUTO_UI_DRIVER;
_Driver->forceNativeFragmentPrograms(nativeOnly);
}
bool CDriverUser::setMonitorColorProperties (const CMonitorColorProperties &properties)
{
NL3D_HAUTO_UI_DRIVER;

View file

@ -363,6 +363,8 @@ void CFlareModel::traverseRender()
}
// setup driver
drv->activeVertexProgram(NULL);
drv->activePixelProgram(NULL);
drv->activeGeometryProgram(NULL);
drv->setupModelMatrix(fs->getLookAtMode() ? CMatrix::Identity : getWorldMatrix());
// we don't change the fustrum to draw 2d shapes : it is costly, and we need to restore it after the drawing has been done
// we setup Z to be (near + far) / 2, and setup x and y to get the screen coordinates we want
@ -565,6 +567,8 @@ void CFlareModel::updateOcclusionQueryBegin(IDriver *drv)
{
nlassert(drv);
drv->activeVertexProgram(NULL);
drv->activePixelProgram(NULL);
drv->activeGeometryProgram(NULL);
drv->setupModelMatrix(CMatrix::Identity);
initStatics();
drv->setColorMask(false, false, false, false); // don't write any pixel during the test
@ -661,6 +665,8 @@ void CFlareModel::occlusionTest(CMesh &mesh, IDriver &drv)
}
drv.setColorMask(false, false, false, false); // don't write any pixel during the test
drv.activeVertexProgram(NULL);
drv.activePixelProgram(NULL);
drv.activeGeometryProgram(NULL);
setupOcclusionMeshMatrix(drv, *_Scene);
drv.activeVertexBuffer(const_cast<CVertexBuffer &>(mesh.getVertexBuffer()));
// query drawn count

View file

@ -0,0 +1,49 @@
/** \file geometry_program.cpp
* Geometry program definition
*/
/* Copyright, 2000, 2001 Nevrax Ltd.
*
* This file is part of NEVRAX NEL.
* NEVRAX NEL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
* NEVRAX NEL 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
* General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with NEVRAX NEL; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#include "std3d.h"
#include <nel/3d/geometry_program.h>
#include <nel/3d/driver.h>
namespace NL3D
{
// ***************************************************************************
CGeometryProgram::CGeometryProgram()
{
}
// ***************************************************************************
CGeometryProgram::~CGeometryProgram ()
{
}
// ***************************************************************************
} // NL3D

View file

@ -0,0 +1,587 @@
/**
* \file gpu_program_params.cpp
* \brief CGPUProgramParams
* \date 2013-09-07 22:17GMT
* \author Jan Boon (Kaetemi)
* CGPUProgramParams
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#include <nel/misc/types_nl.h>
#include <nel/3d/gpu_program_params.h>
// STL includes
// NeL includes
// #include <nel/misc/debug.h>
#include <nel/misc/vector.h>
#include <nel/misc/matrix.h>
// Project includes
#include <nel/3d/driver.h>
using namespace std;
// using namespace NLMISC;
namespace NL3D {
CGPUProgramParams::CGPUProgramParams() : m_First(s_End), m_Last(s_End)
{
}
CGPUProgramParams::~CGPUProgramParams()
{
}
void CGPUProgramParams::copy(CGPUProgramParams *params)
{
size_t offset = params->getBegin();
while (offset != params->getEnd())
{
uint index = params->getIndexByOffset(offset);
const std::string &name = params->getNameByOffset(offset);
size_t local;
uint size = params->getSizeByOffset(offset);
uint count = params->getCountByOffset(offset);
uint nbComponents = size * count;
if (index)
{
local = allocOffset(index, size, count, params->getTypeByOffset(offset));
if (!name.empty())
{
map(index, name);
}
}
else
{
nlassert(!name.empty());
local = allocOffset(name, size, count, params->getTypeByOffset(offset));
}
uint32 *src = params->getPtrUIByOffset(offset);
uint32 *dst = getPtrUIByOffset(local);
for (uint c = 0; c < nbComponents; ++c)
{
dst[c] = src[c];
}
offset = params->getNext(offset);
}
}
void CGPUProgramParams::set1f(uint index, float f0)
{
float *f = getPtrFByOffset(allocOffset(index, 1, 1, Float));
f[0] = f0;
}
void CGPUProgramParams::set2f(uint index, float f0, float f1)
{
float *f = getPtrFByOffset(allocOffset(index, 2, 1, Float));
f[0] = f0;
f[1] = f1;
}
void CGPUProgramParams::set3f(uint index, float f0, float f1, float f2)
{
float *f = getPtrFByOffset(allocOffset(index, 3, 1, Float));
f[0] = f0;
f[1] = f1;
f[2] = f2;
}
void CGPUProgramParams::set4f(uint index, float f0, float f1, float f2, float f3)
{
float *f = getPtrFByOffset(allocOffset(index, 4, 1, Float));
f[0] = f0;
f[1] = f1;
f[2] = f2;
f[3] = f3;
}
void CGPUProgramParams::set1i(uint index, sint32 i0)
{
sint32 *i = getPtrIByOffset(allocOffset(index, 1, 1, Int));
i[0] = i0;
}
void CGPUProgramParams::set2i(uint index, sint32 i0, sint32 i1)
{
sint32 *i = getPtrIByOffset(allocOffset(index, 2, 1, Int));
i[0] = i0;
i[1] = i1;
}
void CGPUProgramParams::set3i(uint index, sint32 i0, sint32 i1, sint32 i2)
{
sint32 *i = getPtrIByOffset(allocOffset(index, 3, 1, Int));
i[0] = i0;
i[1] = i1;
i[2] = i2;
}
void CGPUProgramParams::set4i(uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3)
{
sint32 *i = getPtrIByOffset(allocOffset(index, 4, 1, Int));
i[0] = i0;
i[1] = i1;
i[2] = i2;
i[3] = i3;
}
void CGPUProgramParams::set1ui(uint index, uint32 ui0)
{
uint32 *ui = getPtrUIByOffset(allocOffset(index, 1, 1, UInt));
ui[0] = ui0;
}
void CGPUProgramParams::set2ui(uint index, uint32 ui0, uint32 ui1)
{
uint32 *ui = getPtrUIByOffset(allocOffset(index, 2, 1, UInt));
ui[0] = ui0;
ui[1] = ui1;
}
void CGPUProgramParams::set3ui(uint index, uint32 ui0, uint32 ui1, uint32 ui2)
{
uint32 *ui = getPtrUIByOffset(allocOffset(index, 3, 1, UInt));
ui[0] = ui0;
ui[1] = ui1;
ui[2] = ui2;
}
void CGPUProgramParams::set4ui(uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3)
{
uint32 *ui = getPtrUIByOffset(allocOffset(index, 4, 1, UInt));
ui[0] = ui0;
ui[1] = ui1;
ui[2] = ui2;
ui[3] = ui3;
}
void CGPUProgramParams::set3f(uint index, const NLMISC::CVector& v)
{
float *f = getPtrFByOffset(allocOffset(index, 3, 1, Float));
f[0] = v.x;
f[1] = v.y;
f[2] = v.z;
}
void CGPUProgramParams::set4f(uint index, const NLMISC::CVector& v, float f3)
{
float *f = getPtrFByOffset(allocOffset(index, 4, 1, Float));
f[0] = v.x;
f[1] = v.y;
f[2] = v.z;
f[3] = f3;
}
void CGPUProgramParams::set4x4f(uint index, const NLMISC::CMatrix& m)
{
// TODO: Verify this!
float *f = getPtrFByOffset(allocOffset(index, 4, 4, Float));
NLMISC::CMatrix mt = m;
mt.transpose();
mt.get(f);
}
void CGPUProgramParams::set4fv(uint index, size_t num, const float *src)
{
float *f = getPtrFByOffset(allocOffset(index, 4, num, Float));
size_t nb = 4 * num;
for (uint c = 0; c < nb; ++c)
f[c] = src[c];
}
void CGPUProgramParams::set4iv(uint index, size_t num, const sint32 *src)
{
sint32 *i = getPtrIByOffset(allocOffset(index, 4, num, Int));
size_t nb = 4 * num;
for (uint c = 0; c < nb; ++c)
i[c] = src[c];
}
void CGPUProgramParams::set4uiv(uint index, size_t num, const uint32 *src)
{
uint32 *ui = getPtrUIByOffset(allocOffset(index, 4, num, UInt));
size_t nb = 4 * num;
for (uint c = 0; c < nb; ++c)
ui[c] = src[c];
}
void CGPUProgramParams::unset(uint index)
{
size_t offset = getOffset(index);
if (offset != getEnd())
{
freeOffset(offset);
}
}
void CGPUProgramParams::set1f(const std::string &name, float f0)
{
float *f = getPtrFByOffset(allocOffset(name, 1, 1, Float));
f[0] = f0;
}
void CGPUProgramParams::set2f(const std::string &name, float f0, float f1)
{
float *f = getPtrFByOffset(allocOffset(name, 2, 1, Float));
f[0] = f0;
f[1] = f1;
}
void CGPUProgramParams::set3f(const std::string &name, float f0, float f1, float f2)
{
float *f = getPtrFByOffset(allocOffset(name, 3, 1, Float));
f[0] = f0;
f[1] = f1;
f[2] = f2;
}
void CGPUProgramParams::set4f(const std::string &name, float f0, float f1, float f2, float f3)
{
float *f = getPtrFByOffset(allocOffset(name, 4, 1, Float));
f[0] = f0;
f[1] = f1;
f[2] = f2;
f[3] = f3;
}
void CGPUProgramParams::set1i(const std::string &name, sint32 i0)
{
sint32 *i = getPtrIByOffset(allocOffset(name, 1, 1, Int));
i[0] = i0;
}
void CGPUProgramParams::set2i(const std::string &name, sint32 i0, sint32 i1)
{
sint32 *i = getPtrIByOffset(allocOffset(name, 2, 1, Int));
i[0] = i0;
i[1] = i1;
}
void CGPUProgramParams::set3i(const std::string &name, sint32 i0, sint32 i1, sint32 i2)
{
sint32 *i = getPtrIByOffset(allocOffset(name, 3, 1, Int));
i[0] = i0;
i[1] = i1;
i[2] = i2;
}
void CGPUProgramParams::set4i(const std::string &name, sint32 i0, sint32 i1, sint32 i2, sint32 i3)
{
sint32 *i = getPtrIByOffset(allocOffset(name, 4, 1, Int));
i[0] = i0;
i[1] = i1;
i[2] = i2;
i[3] = i3;
}
void CGPUProgramParams::set1ui(const std::string &name, uint32 ui0)
{
uint32 *ui = getPtrUIByOffset(allocOffset(name, 1, 1, UInt));
ui[0] = ui0;
}
void CGPUProgramParams::set2ui(const std::string &name, uint32 ui0, uint32 ui1)
{
uint32 *ui = getPtrUIByOffset(allocOffset(name, 2, 1, UInt));
ui[0] = ui0;
ui[1] = ui1;
}
void CGPUProgramParams::set3ui(const std::string &name, uint32 ui0, uint32 ui1, uint32 ui2)
{
uint32 *ui = getPtrUIByOffset(allocOffset(name, 3, 1, UInt));
ui[0] = ui0;
ui[1] = ui1;
ui[2] = ui2;
}
void CGPUProgramParams::set4ui(const std::string &name, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3)
{
uint32 *ui = getPtrUIByOffset(allocOffset(name, 4, 1, UInt));
ui[0] = ui0;
ui[1] = ui1;
ui[2] = ui2;
ui[3] = ui3;
}
void CGPUProgramParams::set3f(const std::string &name, const NLMISC::CVector& v)
{
float *f = getPtrFByOffset(allocOffset(name, 3, 1, Float));
f[0] = v.x;
f[1] = v.y;
f[2] = v.z;
}
void CGPUProgramParams::set4f(const std::string &name, const NLMISC::CVector& v, float f3)
{
float *f = getPtrFByOffset(allocOffset(name, 4, 1, Float));
f[0] = v.x;
f[1] = v.y;
f[2] = v.z;
f[3] = f3;
}
void CGPUProgramParams::set4x4f(const std::string &name, const NLMISC::CMatrix& m)
{
// TODO: Verify this!
float *f = getPtrFByOffset(allocOffset(name, 4, 4, Float));
NLMISC::CMatrix mt = m;
mt.transpose();
mt.get(f);
}
void CGPUProgramParams::set4fv(const std::string &name, size_t num, const float *src)
{
float *f = getPtrFByOffset(allocOffset(name, 4, num, Float));
size_t nb = 4 * num;
for (uint c = 0; c < nb; ++c)
f[c] = src[c];
}
void CGPUProgramParams::set4iv(const std::string &name, size_t num, const sint32 *src)
{
sint32 *i = getPtrIByOffset(allocOffset(name, 4, num, Int));
size_t nb = 4 * num;
for (uint c = 0; c < nb; ++c)
i[c] = src[c];
}
void CGPUProgramParams::set4uiv(const std::string &name, size_t num, const uint32 *src)
{
uint32 *ui = getPtrUIByOffset(allocOffset(name, 4, num, UInt));
size_t nb = 4 * num;
for (uint c = 0; c < nb; ++c)
ui[c] = src[c];
}
void CGPUProgramParams::unset(const std::string &name)
{
size_t offset = getOffset(name);
if (offset != getEnd())
{
freeOffset(offset);
}
}
void CGPUProgramParams::map(uint index, const std::string &name)
{
size_t offsetIndex = getOffset(index);
size_t offsetName = getOffset(name);
if (offsetName != getEnd())
{
// Remove possible duplicate
if (offsetIndex != getEnd())
{
freeOffset(offsetIndex);
}
// Set index
m_Meta[offsetName].Index = index;
// Map index to name
if (index >= m_Map.size())
m_Map.resize(index + 1, s_End);
m_Map[index] = offsetName;
}
else if (offsetIndex != getEnd())
{
// Set name
m_Meta[offsetIndex].Name = name;
// Map name to index
m_MapName[name] = offsetIndex;
}
}
/// Allocate specified number of components if necessary
size_t CGPUProgramParams::allocOffset(uint index, uint size, uint count, TType type)
{
nlassert(count > 0); // this code will not properly handle 0
nlassert(size > 0); // this code will not properly handle 0
nlassert(index < 0xFFFF); // sanity check
uint nbComponents = size * count;
size_t offset = getOffset(index);
if (offset != s_End)
{
if (getCountByOffset(offset) >= nbComponents)
{
m_Meta[offset].Type = type;
m_Meta[offset].Size = size;
m_Meta[offset].Count = count;
return offset;
}
if (getCountByOffset(offset) < nbComponents)
{
freeOffset(offset);
}
}
// Allocate space
offset = allocOffset(size, count, type);
// Fill
m_Meta[offset].Index = index;
// Store offset in map
if (index >= m_Map.size())
m_Map.resize(index + 1, s_End);
m_Map[index] = offset;
return offset;
}
/// Allocate specified number of components if necessary
size_t CGPUProgramParams::allocOffset(const std::string &name, uint size, uint count, TType type)
{
nlassert(count > 0); // this code will not properly handle 0
nlassert(size > 0); // this code will not properly handle 0
nlassert(!name.empty()); // sanity check
uint nbComponents = size * count;
size_t offset = getOffset(name);
if (offset != s_End)
{
if (getCountByOffset(offset) >= nbComponents)
{
m_Meta[offset].Type = type;
m_Meta[offset].Size = size;
m_Meta[offset].Count = count;
return offset;
}
if (getCountByOffset(offset) < nbComponents)
{
freeOffset(offset);
}
}
// Allocate space
offset = allocOffset(size, count, type);
// Fill
m_Meta[offset].Name = name;
// Store offset in map
m_MapName[name] = offset;
return offset;
}
/// Allocate specified number of components if necessary
size_t CGPUProgramParams::allocOffset(uint size, uint count, TType type)
{
uint nbComponents = size * count;
// Allocate space
size_t offset = m_Meta.size();
uint blocks = getNbRegistersByComponents(nbComponents); // per 4 components
m_Meta.resize(offset + blocks);
m_Vec.resize(offset + blocks);
// Fill
m_Meta[offset].Size = size;
m_Meta[offset].Count = count;
m_Meta[offset].Type = type;
m_Meta[offset].Prev = m_Last;
m_Meta[offset].Next = s_End;
// Link
if (m_Last == s_End)
{
m_First = m_Last = offset;
}
else
{
nlassert(m_Meta[m_Last].Next == s_End); // code error otherwise
m_Meta[m_Last].Next = offset;
m_Last = offset;
}
return offset;
}
/// Return offset for specified index
size_t CGPUProgramParams::getOffset(uint index) const
{
if (index >= m_Map.size())
return s_End;
return m_Map[index];
}
size_t CGPUProgramParams::getOffset(const std::string &name) const
{
std::map<std::string, size_t>::const_iterator it = m_MapName.find(name);
if (it == m_MapName.end())
return s_End;
return it->second;
}
/// Remove by offset
void CGPUProgramParams::freeOffset(size_t offset)
{
uint index = getIndexByOffset(offset);
if (index != ~0)
{
if (m_Map.size() > index)
{
m_Map[index] = getEnd();
}
}
const std::string &name = getNameByOffset(offset);
if (!name.empty())
{
if (m_MapName.find(name) != m_MapName.end())
{
m_MapName.erase(name);
}
}
if (offset == m_Last)
{
nlassert(m_Meta[offset].Next == s_End);
m_Last = m_Meta[offset].Prev;
}
else
{
nlassert(m_Meta[offset].Next != s_End);
m_Meta[m_Meta[offset].Next].Prev = m_Meta[offset].Prev;
}
if (offset == m_First)
{
nlassert(m_Meta[offset].Prev == s_End);
m_First = m_Meta[offset].Next;
}
else
{
nlassert(m_Meta[offset].Prev != s_End);
m_Meta[m_Meta[offset].Prev].Next = m_Meta[offset].Next;
}
}
} /* namespace NL3D */
/* end of file */

View file

@ -574,7 +574,7 @@ void CLandscape::setDriver(IDriver *drv)
// Does the driver support VertexShader???
// only if VP supported by GPU.
_VertexShaderOk= (_Driver->isVertexProgramSupported() && !_Driver->isVertexProgramEmulated());
_VertexShaderOk= (_Driver->supportVertexProgram() && !_Driver->isVertexProgramEmulated());
// Does the driver has sufficient requirements for Vegetable???
@ -1193,20 +1193,33 @@ void CLandscape::render(const CVector &refineCenter, const CVector &frontVecto
// If VertexShader enabled, setup VertexProgram Constants.
if(_VertexShaderOk)
if (_VertexShaderOk)
{
// c[0..3] take the ModelViewProjection Matrix.
driver->setConstantMatrix(0, IDriver::ModelViewProjection, IDriver::Identity);
// c[4] take useful constants.
driver->setConstant(4, 0, 1, 0.5f, 0);
// c[5] take RefineCenter
driver->setConstant(5, refineCenter);
// c[6] take info for Geomorph trnasition to TileNear.
driver->setConstant(6, CLandscapeGlobals::TileDistFarSqr, CLandscapeGlobals::OOTileDistDeltaSqr, 0, 0);
// c[10] take the fog vector.
driver->setConstantFog(10);
// c[12] take the current landscape Center / delta Pos to apply
driver->setConstant(12, _PZBModelPosition);
bool uprogstate = driver->isUniformProgramState();
uint nbvp = uprogstate ? CLandscapeVBAllocator::MaxVertexProgram : 1;
for (uint i = 0; i < nbvp; ++i)
{
CVertexProgramLandscape *program = _TileVB.getVP(i);
if (program)
{
// activate the program to set the uniforms in the program state for all programs
// note: when uniforms are driver state, the indices must be the same across programs
_TileVB.activateVP(i);
// c[0..3] take the ModelViewProjection Matrix.
driver->setUniformMatrix(IDriver::VertexProgram, program->getUniformIndex(CProgramIndex::ModelViewProjection), IDriver::ModelViewProjection, IDriver::Identity);
// c[4] take useful constants.
driver->setUniform4f(IDriver::VertexProgram, program->idx().ProgramConstants0, 0, 1, 0.5f, 0);
// c[5] take RefineCenter
driver->setUniform3f(IDriver::VertexProgram, program->idx().RefineCenter, refineCenter);
// c[6] take info for Geomorph trnasition to TileNear.
driver->setUniform2f(IDriver::VertexProgram, program->idx().TileDist, CLandscapeGlobals::TileDistFarSqr, CLandscapeGlobals::OOTileDistDeltaSqr);
// c[10] take the fog vector.
driver->setUniformFog(IDriver::VertexProgram, program->getUniformIndex(CProgramIndex::Fog));
// c[12] take the current landscape Center / delta Pos to apply
driver->setUniform3f(IDriver::VertexProgram, program->idx().PZBModelPosition, _PZBModelPosition);
}
}
}

View file

@ -82,7 +82,7 @@ void CLandscapeVBAllocator::updateDriver(IDriver *driver)
deleteVertexProgram();
// Then rebuild VB format, and VertexProgram, if needed.
// Do it only if VP supported by GPU.
setupVBFormatAndVertexProgram(_Driver->isVertexProgramSupported() && !_Driver->isVertexProgramEmulated());
setupVBFormatAndVertexProgram(_Driver->supportVertexProgram() && !_Driver->isVertexProgramEmulated());
// must reallocate the VertexBuffer.
if( _NumVerticesAllocated>0 )
@ -247,14 +247,23 @@ void CLandscapeVBAllocator::activate(uint vpId)
nlassert(_Driver);
nlassert(!_BufferLocked);
activateVP(vpId);
_Driver->activeVertexBuffer(_VB);
}
// ***************************************************************************
void CLandscapeVBAllocator::activateVP(uint vpId)
{
nlassert(_Driver);
// If enabled, activate Vertex program first.
if(_VertexProgram[vpId])
if (_VertexProgram[vpId])
{
//nlinfo("\nSTARTVP\n%s\nENDVP\n", _VertexProgram[vpId]->getProgram().c_str());
nlverify(_Driver->activeVertexProgram(_VertexProgram[vpId]));
}
_Driver->activeVertexBuffer(_VB);
}
@ -516,12 +525,11 @@ const char* NL3D_LandscapeTileLightMapEndProgram=
// ***************************************************************************
void CLandscapeVBAllocator::deleteVertexProgram()
{
for(uint i=0;i<MaxVertexProgram;i++)
for (uint i = 0; i < MaxVertexProgram; ++i)
{
if(_VertexProgram[i])
if (_VertexProgram[i])
{
delete _VertexProgram[i];
_VertexProgram[i]= NULL;
_VertexProgram[i] = NULL; // smartptr
}
}
}
@ -560,9 +568,7 @@ void CLandscapeVBAllocator::setupVBFormatAndVertexProgram(bool withVertexProgr
_VB.initEx();
// Init the Vertex Program.
string vpgram= string(NL3D_LandscapeCommonStartProgram) +
string(NL3D_LandscapeFar0EndProgram);
_VertexProgram[0]= new CVertexProgram(vpgram.c_str());
_VertexProgram[0]= new CVertexProgramLandscape(Far0);
}
else if(_Type==Far1)
{
@ -577,9 +583,7 @@ void CLandscapeVBAllocator::setupVBFormatAndVertexProgram(bool withVertexProgr
_VB.initEx();
// Init the Vertex Program.
string vpgram= string(NL3D_LandscapeCommonStartProgram) +
string(NL3D_LandscapeFar1EndProgram);
_VertexProgram[0]= new CVertexProgram(vpgram.c_str());
_VertexProgram[0] = new CVertexProgramLandscape(Far1);
}
else
{
@ -594,20 +598,74 @@ void CLandscapeVBAllocator::setupVBFormatAndVertexProgram(bool withVertexProgr
_VB.initEx();
// Init the Vertex Program.
string vpgram= string(NL3D_LandscapeCommonStartProgram) +
string(NL3D_LandscapeTileEndProgram);
_VertexProgram[0]= new CVertexProgram(vpgram.c_str());
_VertexProgram[0] = new CVertexProgramLandscape(Tile, false);
// Init the Vertex Program for lightmap pass
vpgram= string(NL3D_LandscapeCommonStartProgram) +
string(NL3D_LandscapeTileLightMapEndProgram);
_VertexProgram[1]= new CVertexProgram(vpgram.c_str());
_VertexProgram[1] = new CVertexProgramLandscape(Tile, true);
}
}
}
CVertexProgramLandscape::CVertexProgramLandscape(CLandscapeVBAllocator::TType type, bool lightMap)
{
// nelvp
{
CSource *source = new CSource();
source->Profile = nelvp;
source->DisplayName = "Landscape/nelvp";
switch (type)
{
case CLandscapeVBAllocator::Far0:
source->DisplayName += "/far0";
source->setSource(std::string(NL3D_LandscapeCommonStartProgram)
+ std::string(NL3D_LandscapeFar0EndProgram));
break;
case CLandscapeVBAllocator::Far1:
source->DisplayName += "/far1";
source->setSource(std::string(NL3D_LandscapeCommonStartProgram)
+ std::string(NL3D_LandscapeFar1EndProgram));
break;
case CLandscapeVBAllocator::Tile:
source->DisplayName += "/tile";
if (lightMap)
{
source->DisplayName += "/lightmap";
source->setSource(std::string(NL3D_LandscapeCommonStartProgram)
+ std::string(NL3D_LandscapeTileLightMapEndProgram));
}
else
{
source->setSource(std::string(NL3D_LandscapeCommonStartProgram)
+ std::string(NL3D_LandscapeTileEndProgram));
}
break;
}
source->ParamIndices["modelViewProjection"] = 0;
source->ParamIndices["programConstants0"] = 4;
source->ParamIndices["refineCenter"] = 5;
source->ParamIndices["tileDist"] = 6;
source->ParamIndices["fog"] = 10;
source->ParamIndices["pzbModelPosition"] = 12;
addSource(source);
}
// TODO_VP_GLSL
{
// ....
}
}
void CVertexProgramLandscape::buildInfo()
{
m_Idx.ProgramConstants0 = getUniformIndex("programConstants0");
nlassert(m_Idx.ProgramConstants0 != ~0);
m_Idx.RefineCenter = getUniformIndex("refineCenter");
nlassert(m_Idx.RefineCenter != ~0);
m_Idx.TileDist = getUniformIndex("tileDist");
nlassert(m_Idx.TileDist != ~0);
m_Idx.PZBModelPosition = getUniformIndex("pzbModelPosition");
nlassert(m_Idx.PZBModelPosition != ~0);
}
} // NL3D

View file

@ -18,7 +18,6 @@
#include "nel/3d/material.h"
#include "nel/3d/texture.h"
#include "nel/3d/shader.h"
#include "nel/3d/driver.h"
#include "nel/misc/stream.h"

View file

@ -32,14 +32,13 @@
namespace NL3D
{
std::auto_ptr<CVertexProgram> CMeshVPPerPixelLight::_VertexProgram[NumVp];
NLMISC::CSmartPtr<CVertexProgramPerPixelLight> CMeshVPPerPixelLight::_VertexProgram[NumVp];
// ***************************************************************************
// Light VP fragment constants start at 24
static const uint VPLightConstantStart = 24;
// ***************************************************************************
// ***************************************************************************
@ -355,18 +354,36 @@ static const char* PPLightingVPCodeTest =
";
***************************************************************/
//=================================================================================
void CMeshVPPerPixelLight::initInstance(CMeshBaseInstance *mbi)
class CVertexProgramPerPixelLight : public CVertexProgramLighted
{
// init the vertexProgram code.
static bool vpCreated= false;
if(!vpCreated)
public:
struct CIdx
{
vpCreated= true;
/// Position or direction of strongest light
uint StrongestLight;
/// Viewer position
uint ViewerPos;
};
CVertexProgramPerPixelLight(uint vp);
virtual ~CVertexProgramPerPixelLight() { };
virtual void buildInfo();
const CIdx &idx() const { return m_Idx; }
private:
CIdx m_Idx;
};
CVertexProgramPerPixelLight::CVertexProgramPerPixelLight(uint vp)
{
// lighted settings
m_FeaturesLighted.SupportSpecular = (vp & 2) != 0;
m_FeaturesLighted.NumActivePointLights = MaxLight - 1;
m_FeaturesLighted.Normalize = false;
m_FeaturesLighted.CtStartNeLVP = VPLightConstantStart;
// nelvp
{
// Gives each vp name
// Bit 0 : 1 when it is a directionnal light
// Bit 1 : 1 when specular is needed
@ -389,34 +406,89 @@ void CMeshVPPerPixelLight::initInstance(CMeshBaseInstance *mbi)
};
uint numvp = sizeof(vpName) / sizeof(const char *);
nlassert(NumVp == numvp); // make sure that it is in sync with header..todo : compile time assert :)
nlassert(CMeshVPPerPixelLight::NumVp == numvp); // make sure that it is in sync with header..todo : compile time assert :)
// \todo yoyo TODO_OPTIM Manage different number of pointLights
// NB: never call getLightVPFragmentNeLVP() with normalize, because already done by PerPixel fragment before.
std::string vpCode = std::string(vpName[vp])
+ std::string("# ***************") // temp for debug
+ CRenderTrav::getLightVPFragmentNeLVP(
m_FeaturesLighted.NumActivePointLights,
m_FeaturesLighted.CtStartNeLVP,
m_FeaturesLighted.SupportSpecular,
m_FeaturesLighted.Normalize)
+ std::string("# ***************") // temp for debug
+ std::string(PPLightingVPCodeEnd);
#ifdef NL_DEBUG
/** For test : parse those programs before they are used.
* As a matter of fact some program will works with the NV_VERTEX_PROGRAM extension,
* but won't with EXT_vertex_shader, because there are some limitations (can't read a temp
* register that hasn't been written before..)
*/
CVPParser vpParser;
CVPParser::TProgram result;
std::string parseOutput;
if (!vpParser.parse(vpCode.c_str(), result, parseOutput))
{
nlwarning(parseOutput.c_str());
nlassert(0);
}
#endif
CSource *source = new CSource();
source->DisplayName = NLMISC::toString("nelvp/MeshVPPerPixel/%i", vp);
source->Profile = CVertexProgram::nelvp;
source->setSource(vpCode);
source->ParamIndices["modelViewProjection"] = 0;
addSource(source);
}
// glsl
{
// TODO_VP_GLSL
}
}
void CVertexProgramPerPixelLight::buildInfo()
{
CVertexProgramLighted::buildInfo();
if (profile() == nelvp)
{
m_Idx.StrongestLight = 4;
if (m_FeaturesLighted.SupportSpecular)
{
m_Idx.ViewerPos = 5;
}
else
{
m_Idx.ViewerPos = ~0;
}
}
else
{
// TODO_VP_GLSL
}
nlassert(m_Idx.StrongestLight != ~0);
if (m_FeaturesLighted.SupportSpecular)
{
nlassert(m_Idx.ViewerPos != ~0);
}
}
//=================================================================================
void CMeshVPPerPixelLight::initInstance(CMeshBaseInstance *mbi)
{
// init the vertexProgram code.
static bool vpCreated= false;
if (!vpCreated)
{
vpCreated = true;
for (uint vp = 0; vp < NumVp; ++vp)
{
// \todo yoyo TODO_OPTIM Manage different number of pointLights
// NB: never call getLightVPFragment() with normalize, because already done by PerPixel fragment before.
std::string vpCode = std::string(vpName[vp])
+ std::string("# ***************") // temp for debug
+ CRenderTrav::getLightVPFragment(CRenderTrav::MaxVPLight-1, VPLightConstantStart, (vp & 2) != 0, false)
+ std::string("# ***************") // temp for debug
+ std::string(PPLightingVPCodeEnd);
#ifdef NL_DEBUG
/** For test : parse those programs before they are used.
* As a matter of fact some program will works with the NV_VERTEX_PROGRAM extension,
* but won't with EXT_vertex_shader, because there are some limitations (can't read a temp
* register that hasn't been written before..)
*/
CVPParser vpParser;
CVPParser::TProgram result;
std::string parseOutput;
if (!vpParser.parse(vpCode.c_str(), result, parseOutput))
{
nlwarning(parseOutput.c_str());
nlassert(0);
}
#endif
_VertexProgram[vp]= std::auto_ptr<CVertexProgram>(new CVertexProgram(vpCode.c_str()));
_VertexProgram[vp] = new CVertexProgramPerPixelLight(vp);
}
}
}
@ -428,7 +500,7 @@ bool CMeshVPPerPixelLight::begin(IDriver *drv,
{
// test if supported by driver
if (!
(drv->isVertexProgramSupported()
(drv->supportVertexProgram()
&& !drv->isVertexProgramEmulated()
&& drv->supportPerPixelLighting(SpecularLighting)
)
@ -437,11 +509,13 @@ bool CMeshVPPerPixelLight::begin(IDriver *drv,
return false;
}
//
enable(true, drv); // must enable the vertex program before the vb is activated
CVertexProgramPerPixelLight *program = _ActiveVertexProgram;
nlassert(program);
//
CRenderTrav *renderTrav= &scene->getRenderTrav();
/// Setup for gouraud lighting
renderTrav->beginVPLightSetup(VPLightConstantStart,
SpecularLighting,
invertedModelMat);
renderTrav->beginVPLightSetup(program, invertedModelMat);
//
sint strongestLightIndex = renderTrav->getStrongestLightIndex();
if (strongestLightIndex == -1) return false; // if no strongest light, disable this vertex program
@ -455,7 +529,7 @@ bool CMeshVPPerPixelLight::begin(IDriver *drv,
{
// put light direction in object space
NLMISC::CVector lPos = invertedModelMat.mulVector(strongestLight.getDirection());
drv->setConstant(4, lPos);
drv->setUniform3f(IDriver::VertexProgram, program->idx().StrongestLight, lPos);
_IsPointLight = false;
}
break;
@ -463,7 +537,7 @@ bool CMeshVPPerPixelLight::begin(IDriver *drv,
{
// put light in object space
NLMISC::CVector lPos = invertedModelMat * strongestLight.getPosition();
drv->setConstant(4, lPos);
drv->setUniform3f(IDriver::VertexProgram, program->idx().StrongestLight, lPos);
_IsPointLight = true;
}
break;
@ -477,14 +551,12 @@ bool CMeshVPPerPixelLight::begin(IDriver *drv,
{
// viewer pos in object space
NLMISC::CVector vPos = invertedModelMat * viewerPos;
drv->setConstant(5, vPos);
drv->setUniform3f(IDriver::VertexProgram, program->idx().ViewerPos, vPos);
}
// c[0..3] take the ModelViewProjection Matrix. After setupModelMatrix();
drv->setConstantMatrix(0, IDriver::ModelViewProjection, IDriver::Identity);
//
enable(true, drv); // must enable the vertex program before the vb is activated
//
drv->setUniformMatrix(IDriver::VertexProgram, program->getUniformIndex(CProgramIndex::ModelViewProjection), IDriver::ModelViewProjection, IDriver::Identity);
return true;
}
@ -521,11 +593,13 @@ void CMeshVPPerPixelLight::enable(bool enabled, IDriver *drv)
| (SpecularLighting ? 2 : 0)
| (_IsPointLight ? 1 : 0);
//
drv->activeVertexProgram(_VertexProgram[idVP].get());
drv->activeVertexProgram((CVertexProgramPerPixelLight *)_VertexProgram[idVP]);
_ActiveVertexProgram = _VertexProgram[idVP];
}
else
{
drv->activeVertexProgram(NULL);
_ActiveVertexProgram = NULL;
}
_Enabled = enabled;
}
@ -538,6 +612,8 @@ bool CMeshVPPerPixelLight::setupForMaterial(const CMaterial &mat,
)
{
bool enabled = (mat.getShader() == CMaterial::PerPixelLighting || mat.getShader() == CMaterial::PerPixelLightingNoSpec);
bool change = (enabled != _Enabled);
enable(enabled, drv); // enable disable the vertex program (for material that don't have the right shader)
if (enabled)
{
CRenderTrav *renderTrav= &scene->getRenderTrav();
@ -547,8 +623,6 @@ bool CMeshVPPerPixelLight::setupForMaterial(const CMaterial &mat,
renderTrav->getStrongestLightColors(pplDiffuse, pplSpecular);
drv->setPerPixelLightingLight(pplDiffuse, pplSpecular, mat.getShininess());
}
bool change = (enabled != _Enabled);
enable(enabled, drv); // enable disable the vertex program (for material that don't have the right shader)
return change;
}
//=================================================================================

View file

@ -35,11 +35,11 @@ namespace NL3D
// ***************************************************************************
// Light VP fragment constants start at 24
static const uint VPLightConstantStart= 24;
static const uint VPLightConstantStart = 24;
// ***************************************************************************
std::auto_ptr<CVertexProgram> CMeshVPWindTree::_VertexProgram[CMeshVPWindTree::NumVp];
NLMISC::CSmartPtr<CVertexProgramWindTree> CMeshVPWindTree::_VertexProgram[CMeshVPWindTree::NumVp];
static const char* WindTreeVPCodeWave=
"!!VP1.0 \n\
@ -79,6 +79,83 @@ static const char* WindTreeVPCodeEnd=
END \n\
";
class CVertexProgramWindTree : public CVertexProgramLighted
{
public:
struct CIdx
{
uint ProgramConstants[3];
uint WindLevel1;
uint WindLevel2[4];
uint WindLevel3[4];
};
CVertexProgramWindTree(uint numPls, bool specular, bool normalize);
virtual ~CVertexProgramWindTree() { };
virtual void buildInfo();
const CIdx &idx() const { return m_Idx; }
bool PerMeshSetup;
private:
CIdx m_Idx;
};
CVertexProgramWindTree::CVertexProgramWindTree(uint numPls, bool specular, bool normalize)
{
// lighted settings
m_FeaturesLighted.SupportSpecular = specular;
m_FeaturesLighted.NumActivePointLights = numPls;
m_FeaturesLighted.Normalize = normalize;
m_FeaturesLighted.CtStartNeLVP = VPLightConstantStart;
// constants cache
PerMeshSetup = false;
// nelvp
{
std::string vpCode = std::string(WindTreeVPCodeWave)
+ CRenderTrav::getLightVPFragmentNeLVP(numPls, VPLightConstantStart, specular, normalize)
+ WindTreeVPCodeEnd;
CSource *source = new CSource();
source->DisplayName = NLMISC::toString("nelvp/MeshVPWindTree/%i/%s/%s", numPls, specular ? "spec" : "nospec", normalize ? "normalize" : "nonormalize");
source->Profile = CVertexProgram::nelvp;
source->setSource(vpCode);
source->ParamIndices["modelViewProjection"] = 0;
source->ParamIndices["fog"] = 6;
addSource(source);
}
// TODO_VP_GLSL
}
void CVertexProgramWindTree::buildInfo()
{
CVertexProgramLighted::buildInfo();
if (profile() == nelvp)
{
m_Idx.ProgramConstants[0] = 8;
m_Idx.ProgramConstants[1] = 9;
m_Idx.ProgramConstants[2] = 10;
m_Idx.WindLevel1 = 15;
m_Idx.WindLevel2[0] = 16;
m_Idx.WindLevel2[1] = 17;
m_Idx.WindLevel2[2] = 18;
m_Idx.WindLevel2[3] = 19;
m_Idx.WindLevel3[0] = 20;
m_Idx.WindLevel3[1] = 21;
m_Idx.WindLevel3[2] = 22;
m_Idx.WindLevel3[3] = 23;
}
else
{
// TODO_VP_GLSL
}
}
// ***************************************************************************
float CMeshVPWindTree::speedCos(float angle)
{
@ -142,9 +219,6 @@ void CMeshVPWindTree::initInstance(CMeshBaseInstance *mbi)
// All vpcode and begin() written for HrcDepth==3
nlassert(HrcDepth==3);
// combine fragments.
string vpCode;
// For all possible VP.
for(uint i=0;i<NumVp;i++)
{
@ -153,11 +227,8 @@ void CMeshVPWindTree::initInstance(CMeshBaseInstance *mbi)
bool normalize= (i&1)!=0;
bool specular= (i&2)!=0;
// combine fragments
vpCode= string(WindTreeVPCodeWave)
+ CRenderTrav::getLightVPFragment(numPls, VPLightConstantStart, specular, normalize)
+ WindTreeVPCodeEnd;
_VertexProgram[i]= std::auto_ptr<CVertexProgram>(new CVertexProgram(vpCode.c_str()));
// combine
_VertexProgram[i] = new CVertexProgramWindTree(numPls, normalize, specular);
}
}
@ -203,21 +274,27 @@ inline void CMeshVPWindTree::setupPerMesh(IDriver *driver, CScene *scene)
}
}
CVertexProgramWindTree *program = _ActiveVertexProgram;
nlassert(program);
// Setup common constants for each instances.
// c[8] take useful constants.
static float ct8[4]= {0, 1, 0.5f, 2};
driver->setConstant(8, 1, ct8);
driver->setUniform4f(IDriver::VertexProgram, program->idx().ProgramConstants[0],
0, 1, 0.5f, 2);
// c[9] take other useful constants.
static float ct9[4]= {3.f, 0.f, -1.f, -2.f};
driver->setConstant(9, 1, ct9);
driver->setUniform4f(IDriver::VertexProgram, program->idx().ProgramConstants[1],
3.f, 0.f, -1.f, -2.f);
// c[10] take Number of phase (4) for level2 and 3. -0.01 to avoid int value == 4.
static float ct10[4]= {4-0.01f, 0, 0, 0};
driver->setConstant(10, 1, ct10);
driver->setUniform4f(IDriver::VertexProgram, program->idx().ProgramConstants[2],
4-0.01f, 0, 0, 0);
}
// ***************************************************************************
inline void CMeshVPWindTree::setupPerInstanceConstants(IDriver *driver, CScene *scene, CMeshBaseInstance *mbi, const NLMISC::CMatrix &invertedModelMat)
{
CVertexProgramWindTree *program = _ActiveVertexProgram;
nlassert(program);
// get instance info
float instancePhase= mbi->_VPWindTreePhase;
@ -238,16 +315,18 @@ inline void CMeshVPWindTree::setupPerInstanceConstants(IDriver *driver, CScene
setupLighting(scene, mbi, invertedModelMat);
// c[0..3] take the ModelViewProjection Matrix. After setupModelMatrix();
driver->setConstantMatrix(0, IDriver::ModelViewProjection, IDriver::Identity);
driver->setUniformMatrix(IDriver::VertexProgram, program->getUniformIndex(CProgramIndex::ModelViewProjection),
IDriver::ModelViewProjection, IDriver::Identity);
// c[4..7] take the ModelView Matrix. After setupModelMatrix();00
driver->setConstantFog(6);
driver->setUniformFog(IDriver::VertexProgram, program->getUniformIndex(CProgramIndex::Fog));
// c[15] take Wind of level 0.
float f;
f= _CurrentTime[0] + instancePhase;
f= speedCos(f) + Bias[0];
driver->setConstant(15, maxDeltaPosOS[0]*f );
driver->setUniform3f(IDriver::VertexProgram, program->idx().WindLevel1,
maxDeltaPosOS[0]*f );
// c[16-19] take Wind of level 1.
@ -255,16 +334,20 @@ inline void CMeshVPWindTree::setupPerInstanceConstants(IDriver *driver, CScene
float instTime1= _CurrentTime[1] + instancePhase;
// phase 0.
f= speedCos( instTime1+0 ) + Bias[1];
driver->setConstant(16+0, maxDeltaPosOS[1]*f);
driver->setUniform3f(IDriver::VertexProgram, program->idx().WindLevel2[0],
maxDeltaPosOS[1]*f);
// phase 1.
f= speedCos( instTime1+0.25f ) + Bias[1];
driver->setConstant(16+1, maxDeltaPosOS[1]*f);
driver->setUniform3f(IDriver::VertexProgram, program->idx().WindLevel2[1],
maxDeltaPosOS[1]*f);
// phase 2.
f= speedCos( instTime1+0.50f ) + Bias[1];
driver->setConstant(16+2, maxDeltaPosOS[1]*f);
driver->setUniform3f(IDriver::VertexProgram, program->idx().WindLevel2[2],
maxDeltaPosOS[1]*f);
// phase 3.
f= speedCos( instTime1+0.75f ) + Bias[1];
driver->setConstant(16+3, maxDeltaPosOS[1]*f);
driver->setUniform3f(IDriver::VertexProgram, program->idx().WindLevel2[3],
maxDeltaPosOS[1]*f);
// c[20, 23] take Wind of level 2.
@ -272,22 +355,46 @@ inline void CMeshVPWindTree::setupPerInstanceConstants(IDriver *driver, CScene
float instTime2= _CurrentTime[2] + instancePhase;
// phase 0.
f= speedCos( instTime2+0 ) + Bias[2];
driver->setConstant(20+0, maxDeltaPosOS[2]*f);
driver->setUniform3f(IDriver::VertexProgram, program->idx().WindLevel3[0],
maxDeltaPosOS[2]*f);
// phase 1.
f= speedCos( instTime2+0.25f ) + Bias[2];
driver->setConstant(20+1, maxDeltaPosOS[2]*f);
driver->setUniform3f(IDriver::VertexProgram, program->idx().WindLevel3[1],
maxDeltaPosOS[2]*f);
// phase 2.
f= speedCos( instTime2+0.50f ) + Bias[2];
driver->setConstant(20+2, maxDeltaPosOS[2]*f);
driver->setUniform3f(IDriver::VertexProgram, program->idx().WindLevel3[2],
maxDeltaPosOS[2]*f);
// phase 3.
f= speedCos( instTime2+0.75f ) + Bias[2];
driver->setConstant(20+3, maxDeltaPosOS[2]*f);
driver->setUniform3f(IDriver::VertexProgram, program->idx().WindLevel3[3],
maxDeltaPosOS[2]*f);
}
// ***************************************************************************
bool CMeshVPWindTree::begin(IDriver *driver, CScene *scene, CMeshBaseInstance *mbi, const NLMISC::CMatrix &invertedModelMat, const NLMISC::CVector & /*viewerPos*/)
{
if (!(driver->isVertexProgramSupported() && !driver->isVertexProgramEmulated())) return false;
if (!(driver->supportVertexProgram() && !driver->isVertexProgramEmulated())) return false;
// Activate the good VertexProgram
//===============
// Get how many pointLights are setuped now.
nlassert(scene != NULL);
CRenderTrav *renderTrav= &scene->getRenderTrav();
sint numPls= renderTrav->getNumVPLights()-1;
clamp(numPls, 0, CRenderTrav::MaxVPLight-1);
// Enable normalize only if requested by user. Because lighting don't manage correct "scale lighting"
uint idVP= (SpecularLighting?2:0) + (driver->isForceNormalize()?1:0) ;
// correct VP id for correct unmber of pls.
idVP= numPls*4 + idVP;
// activate VP.
driver->activeVertexProgram(_VertexProgram[idVP]);
_ActiveVertexProgram = _VertexProgram[idVP];
// precompute mesh
@ -296,22 +403,7 @@ bool CMeshVPWindTree::begin(IDriver *driver, CScene *scene, CMeshBaseInstance *m
// Setup instance constants
setupPerInstanceConstants(driver, scene, mbi, invertedModelMat);
// Activate the good VertexProgram
//===============
// Get how many pointLights are setuped now.
nlassert(scene != NULL);
CRenderTrav *renderTrav= &scene->getRenderTrav();
sint numPls= renderTrav->getNumVPLights()-1;
clamp(numPls, 0, CRenderTrav::MaxVPLight-1);
// Enable normalize only if requested by user. Because lighting don't manage correct "scale lighting"
uint idVP= (SpecularLighting?2:0) + (driver->isForceNormalize()?1:0) ;
// correct VP id for correct unmber of pls.
idVP= numPls*4 + idVP;
// activate VP.
driver->activeVertexProgram(_VertexProgram[idVP].get());
return true;
@ -322,6 +414,7 @@ void CMeshVPWindTree::end(IDriver *driver)
{
// Disable the VertexProgram
driver->activeVertexProgram(NULL);
_ActiveVertexProgram = NULL;
}
// ***************************************************************************
@ -347,7 +440,8 @@ void CMeshVPWindTree::setupLighting(CScene *scene, CMeshBaseInstance *mbi, const
nlassert(scene != NULL);
CRenderTrav *renderTrav= &scene->getRenderTrav();
// setup cte for lighting
renderTrav->beginVPLightSetup(VPLightConstantStart, SpecularLighting, invertedModelMat);
CVertexProgramWindTree *program = _ActiveVertexProgram;
renderTrav->beginVPLightSetup(program, invertedModelMat);
}
@ -367,30 +461,29 @@ bool CMeshVPWindTree::supportMeshBlockRendering() const
// ***************************************************************************
bool CMeshVPWindTree::isMBRVpOk(IDriver *driver) const
{
return driver->isVertexProgramSupported() && !driver->isVertexProgramEmulated();
return driver->supportVertexProgram() && !driver->isVertexProgramEmulated();
}
// ***************************************************************************
void CMeshVPWindTree::beginMBRMesh(IDriver *driver, CScene *scene)
{
// precompute mesh
setupPerMesh(driver, scene);
/* Since need a VertexProgram Activation before activeVBHard, activate a default one
bet the common one will be "NoPointLight, NoSpecular, No ForceNormalize" => 0.
*/
_LastMBRIdVP= 0;
_LastMBRIdVP = 0;
// activate VP.
driver->activeVertexProgram(_VertexProgram[_LastMBRIdVP].get());
driver->activeVertexProgram(_VertexProgram[_LastMBRIdVP]);
_ActiveVertexProgram = _VertexProgram[_LastMBRIdVP];
// precompute mesh
setupPerMesh(driver, scene);
_VertexProgram[_LastMBRIdVP]->PerMeshSetup = true;
}
// ***************************************************************************
void CMeshVPWindTree::beginMBRInstance(IDriver *driver, CScene *scene, CMeshBaseInstance *mbi, const NLMISC::CMatrix &invertedModelMat)
{
// setup first constants for this instance
setupPerInstanceConstants(driver, scene, mbi, invertedModelMat);
// Get how many pointLights are setuped now.
nlassert(scene != NULL);
CRenderTrav *renderTrav= &scene->getRenderTrav();
@ -398,16 +491,27 @@ void CMeshVPWindTree::beginMBRInstance(IDriver *driver, CScene *scene, CMeshBase
clamp(numPls, 0, CRenderTrav::MaxVPLight-1);
// Enable normalize only if requested by user. Because lighting don't manage correct "scale lighting"
uint idVP= (SpecularLighting?2:0) + (driver->isForceNormalize()?1:0) ;
uint idVP = (SpecularLighting?2:0) + (driver->isForceNormalize()?1:0) ;
// correct VP id for correct number of pls.
idVP= numPls*4 + idVP;
idVP = numPls*4 + idVP;
// re-activate VP if idVP different from last setup
if( idVP!=_LastMBRIdVP )
if(idVP != _LastMBRIdVP)
{
_LastMBRIdVP= idVP;
driver->activeVertexProgram(_VertexProgram[_LastMBRIdVP].get());
driver->activeVertexProgram(_VertexProgram[_LastMBRIdVP]);
_ActiveVertexProgram = _VertexProgram[_LastMBRIdVP];
if (!_VertexProgram[_LastMBRIdVP]->PerMeshSetup)
{
// precompute mesh
setupPerMesh(driver, scene);
_VertexProgram[_LastMBRIdVP]->PerMeshSetup = true;
}
}
// setup first constants for this instance
setupPerInstanceConstants(driver, scene, mbi, invertedModelMat);
}
// ***************************************************************************
@ -415,6 +519,7 @@ void CMeshVPWindTree::endMBRMesh(IDriver *driver)
{
// Disable the VertexProgram
driver->activeVertexProgram(NULL);
_ActiveVertexProgram = NULL;
}
// ***************************************************************************

View file

@ -0,0 +1,49 @@
/** \file pixel_program.cpp
* Pixel program definition
*/
/* Copyright, 2000, 2001 Nevrax Ltd.
*
* This file is part of NEVRAX NEL.
* NEVRAX NEL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
* NEVRAX NEL 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
* General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with NEVRAX NEL; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#include "std3d.h"
#include <nel/3d/pixel_program.h>
#include <nel/3d/driver.h>
namespace NL3D
{
// ***************************************************************************
CPixelProgram::CPixelProgram()
{
}
// ***************************************************************************
CPixelProgram::~CPixelProgram ()
{
}
// ***************************************************************************
} // NL3D

117
code/nel/src/3d/program.cpp Normal file
View file

@ -0,0 +1,117 @@
/**
* \file program.cpp
* \brief IProgram
* \date 2013-09-07 15:00GMT
* \author Jan Boon (Kaetemi)
* IProgram
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#include <nel/misc/types_nl.h>
#include <nel/3d/program.h>
// STL includes
// NeL includes
// #include <nel/misc/debug.h>
#include <nel/misc/string_mapper.h>
// Project includes
#include <nel/3d/driver.h>
using namespace std;
// using namespace NLMISC;
namespace NL3D {
// ***************************************************************************
IProgramDrvInfos::IProgramDrvInfos(IDriver *drv, ItGPUPrgDrvInfoPtrList it)
{
_Driver = drv;
_DriverIterator = it;
}
// ***************************************************************************
IProgramDrvInfos::~IProgramDrvInfos ()
{
_Driver->removeGPUPrgDrvInfoPtr(_DriverIterator);
}
// ***************************************************************************
IProgram::IProgram()
{
}
// ***************************************************************************
IProgram::~IProgram()
{
// Must kill the drv mirror of this program.
m_DrvInfo.kill();
}
const char *CProgramIndex::Names[NUM_UNIFORMS] =
{
"modelView",
"modelViewInverse",
"modelViewTranspose",
"modelViewInverseTranspose",
"projection",
"projectionInverse",
"projectionTranspose",
"projectionInverseTranspose",
"modelViewProjection",
"modelViewProjectionInverse",
"modelViewProjectionTranspose",
"modelViewProjectionInverseTranspose",
"fog",
};
void IProgram::buildInfo(CSource *source)
{
nlassert(!m_Source);
m_Source = source;
// Fill index cache
for (int i = 0; i < CProgramIndex::NUM_UNIFORMS; ++i)
{
m_Index.Indices[i] = getUniformIndex(m_Index.Names[i]);
}
buildInfo();
}
void IProgram::buildInfo()
{
}
} /* namespace NL3D */
/* end of file */

View file

@ -786,7 +786,7 @@ void CPSMultiTexturedParticle::setupMaterial(ITexture *primary, IDriver *driver,
/// if bump is used, the matrix must be setupped each time (not a material field)
if (!_ForceBasicCaps && isMultiTextureEnabled() && _MainOp == EnvBumpMap)
{
if (driver->isTextureAddrModeSupported(CMaterial::OffsetTexture))
if (driver->supportTextureAddrMode(CMaterial::OffsetTexture))
{
CTextureBump *tb = dynamic_cast<CTextureBump *>((ITexture *) _Texture2);
if (tb != NULL)
@ -858,7 +858,7 @@ void CPSMultiTexturedParticle::setupMaterial(ITexture *primary, IDriver *driver,
}
else
{
if (!_ForceBasicCaps && (driver->isTextureAddrModeSupported(CMaterial::OffsetTexture) || driver->supportEMBM())) // envbumpmap supported ?
if (!_ForceBasicCaps && (driver->supportTextureAddrMode(CMaterial::OffsetTexture) || driver->supportEMBM())) // envbumpmap supported ?
{
CTextureBump *tb = dynamic_cast<CTextureBump *>((ITexture *) _Texture2);
if (tb != NULL)
@ -917,7 +917,7 @@ void CPSMultiTexturedParticle::setupMultiTexEnv(TOperator op, ITexture *tex1, IT
mat.enableTexAddrMode(false);
break;
case EnvBumpMap:
if (drv.isTextureAddrModeSupported(CMaterial::OffsetTexture))
if (drv.supportTextureAddrMode(CMaterial::OffsetTexture))
{
mat.setTexture(0, tex2);
mat.setTexture(1, tex1);
@ -1113,7 +1113,7 @@ void CPSMultiTexturedParticle::enumTexs(std::vector<NLMISC::CSmartPtr<ITexture>
NL_PS_FUNC(CPSMultiTexturedParticle_enumTexs)
if (_MainOp == EnvBumpMap && !_ForceBasicCaps)
{
if (drv.isTextureAddrModeSupported(CMaterial::OffsetTexture) || drv.supportEMBM())
if (drv.supportTextureAddrMode(CMaterial::OffsetTexture) || drv.supportEMBM())
{
if (_Texture2) dest.push_back(_Texture2);
}
@ -1132,7 +1132,7 @@ bool CPSMultiTexturedParticle::isAlternateTextureUsed(IDriver &driver) const
NL_PS_FUNC(CPSMultiTexturedParticle_isAlternateTextureUsed)
if (!isTouched() && areBasicCapsForcedLocal() == areBasicCapsForced()) return (_MultiTexState & AlternateTextureUsed) != 0;
if (_MainOp != EnvBumpMap) return false;
return _ForceBasicCaps || (!driver.isTextureAddrModeSupported(CMaterial::OffsetTexture) && !driver.supportEMBM());
return _ForceBasicCaps || (!driver.supportTextureAddrMode(CMaterial::OffsetTexture) && !driver.supportEMBM());
}
} // NL3D

View file

@ -762,13 +762,15 @@ void CRenderTrav::changeLightSetup(CLightContribution *lightContribution, bool
// ***************************************************************************
void CRenderTrav::beginVPLightSetup(uint ctStart, bool supportSpecular, const CMatrix &invObjectWM)
void CRenderTrav::beginVPLightSetup(CVertexProgramLighted *program, const CMatrix &invObjectWM)
{
uint i;
nlassert(MaxVPLight==4);
_VPNumLights= min(_NumLightEnabled, (uint)MaxVPLight);
_VPCurrentCtStart= ctStart;
_VPSupportSpecular= supportSpecular;
// _VPCurrentCtStart= ctStart;
// _VPSupportSpecular= supportSpecular;
_VPCurrent = program;
bool supportSpecular = program->featuresLighted().SupportSpecular;
// Prepare Colors (to be multiplied by material)
//================
@ -786,8 +788,11 @@ void CRenderTrav::beginVPLightSetup(uint ctStart, bool supportSpecular, const C
// reset other to 0.
for(; i<MaxVPLight; i++)
{
_VPLightDiffuse[i]= CRGBA::Black;
Driver->setConstant(_VPCurrentCtStart+1+i, 0.f, 0.f, 0.f, 0.f);
_VPLightDiffuse[i] = CRGBA::Black;
if (program->idxLighted().Diffuse[i] != ~0)
{
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Diffuse[i], 0.f, 0.f, 0.f, 0.f);
}
}
// Specular. _VPCurrentCtStart+5 to 8 (only if supportSpecular)
if(supportSpecular)
@ -800,7 +805,10 @@ void CRenderTrav::beginVPLightSetup(uint ctStart, bool supportSpecular, const C
for(; i<MaxVPLight; i++)
{
_VPLightSpecular[i]= CRGBA::Black;
Driver->setConstant(_VPCurrentCtStart+5+i, 0.f, 0.f, 0.f, 0.f);
if (program->idxLighted().Specular[i] != ~0)
{
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Specular[i], 0.f, 0.f, 0.f, 0.f);
}
}
}
@ -816,40 +824,24 @@ void CRenderTrav::beginVPLightSetup(uint ctStart, bool supportSpecular, const C
lightDir= invObjectWM.mulVector(_DriverLight[0].getDirection());
lightDir.normalize();
lightDir= -lightDir;
if(supportSpecular)
{
// Setup lightDir.
Driver->setConstant(_VPCurrentCtStart+9, lightDir);
}
else
{
// Setup lightDir. NB: no specular color!
Driver->setConstant(_VPCurrentCtStart+5, lightDir);
}
Driver->setUniform3f(IDriver::VertexProgram, program->idxLighted().DirOrPos[0], lightDir); // The sun is the same for every instance.
// Setup PointLights
//================
uint startPLPos;
if(supportSpecular)
if (supportSpecular)
{
// Setup eye in objectSpace for localViewer
Driver->setConstant(_VPCurrentCtStart+11, eye);
// Start at 12.
startPLPos= 12;
}
else
{
// Start at 6.
startPLPos= 6;
Driver->setUniform3f(IDriver::VertexProgram, program->idxLighted().EyePosition, eye);
}
// For all pointLight enabled (other are black: don't matter)
for(i=1; i<_VPNumLights; i++)
{
// Setup position of light.
CVector lightPos;
lightPos= invObjectWM * _DriverLight[i].getPosition();
Driver->setConstant(_VPCurrentCtStart+startPLPos+(i-1), lightPos);
lightPos = invObjectWM * _DriverLight[i].getPosition();
Driver->setUniform3f(IDriver::VertexProgram, program->idxLighted().DirOrPos[i], lightPos);
}
@ -860,6 +852,9 @@ void CRenderTrav::beginVPLightSetup(uint ctStart, bool supportSpecular, const C
// ***************************************************************************
void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool excludeStrongest)
{
CVertexProgramLighted *program = _VPCurrent;
nlassert(program);
// Must test if at least done one time.
if(!_VPMaterialCacheDirty)
{
@ -869,7 +864,7 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
_VPMaterialCacheDiffuse == mat.getDiffuse().getPacked() )
{
// Same Diffuse part, test if same specular if necessary
if( !_VPSupportSpecular ||
if( !program->featuresLighted().SupportSpecular ||
( _VPMaterialCacheSpecular == mat.getSpecular().getPacked() &&
_VPMaterialCacheShininess == mat.getShininess() ) )
{
@ -899,7 +894,7 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
// setup Ambient + Emissive
color= _VPFinalAmbient * mat.getAmbient();
color+= mat.getEmissive();
Driver->setConstant(_VPCurrentCtStart+0, 1, &color.R);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Ambient, color);
// is the strongest light is not excluded, its index should have been setup to _VPNumLights
@ -908,7 +903,7 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
for(i = 0; i < strongestLightIndex; ++i)
{
color= _VPLightDiffuse[i] * matDiff;
Driver->setConstant(_VPCurrentCtStart+1+i, 1, &color.R);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Diffuse[i], color);
}
@ -917,24 +912,24 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
color= _VPLightDiffuse[i] * matDiff;
_StrongestLightDiffuse.set((uint8) (255.f * color.R), (uint8) (255.f * color.G), (uint8) (255.f * color.B), (uint8) (255.f * color.A));
// setup strongest light to black for the gouraud part
Driver->setConstant(_VPCurrentCtStart + 1 + i, 0.f, 0.f, 0.f, 0.f);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Diffuse[i], 0.f, 0.f, 0.f, 0.f);
++i;
// setup other lights
for(; i < _VPNumLights; i++)
{
color= _VPLightDiffuse[i] * matDiff;
Driver->setConstant(_VPCurrentCtStart + 1 + i, 1, &color.R);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Diffuse[i], color);
}
}
// setup Specular
if(_VPSupportSpecular)
if (program->featuresLighted().SupportSpecular)
{
for(i = 0; i < strongestLightIndex; ++i)
{
color= _VPLightSpecular[i] * matSpec;
color.A= specExp;
Driver->setConstant(_VPCurrentCtStart+5+i, 1, &color.R);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Specular[i], color);
}
if (i != _VPNumLights)
@ -943,14 +938,14 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
_StrongestLightSpecular.set((uint8) (255.f * color.R), (uint8) (255.f * color.G), (uint8) (255.f * color.B), (uint8) (255.f * color.A));
// setup strongest light to black (for gouraud part)
Driver->setConstant(_VPCurrentCtStart + 5 + i, 0.f, 0.f, 0.f, 0.f);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Specular[i], 0.f, 0.f, 0.f, 0.f);
++i;
// setup other lights
for(; i < _VPNumLights; i++)
{
color= _VPLightSpecular[i] * matSpec;
color.A= specExp;
Driver->setConstant(_VPCurrentCtStart + 5 + i, 1, &color.R);
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Specular[i], color);
}
}
}
@ -959,10 +954,7 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
static float alphaCte[4]= {0,0,1,0};
alphaCte[3]= matDiff.A;
// setup at good place
if(_VPSupportSpecular)
Driver->setConstant(_VPCurrentCtStart+10, 1, alphaCte);
else
Driver->setConstant(_VPCurrentCtStart+9, 1, alphaCte);
Driver->setUniform4fv(IDriver::VertexProgram, program->idxLighted().DiffuseAlpha, 1, alphaCte);
}
// ***************************************************************************
@ -1168,8 +1160,66 @@ static void strReplaceAll(string &strInOut, const string &tokenSrc, const string
}
}
void CVertexProgramLighted::buildInfo()
{
CVertexProgram::buildInfo();
if (profile() == nelvp)
{
// Fixed uniform locations
m_IdxLighted.Ambient = m_FeaturesLighted.CtStartNeLVP + 0;
for (uint i = 0; i < MaxLight; ++i)
{
m_IdxLighted.Diffuse[i] = m_FeaturesLighted.CtStartNeLVP + 1 + i;
}
if (m_FeaturesLighted.SupportSpecular)
{
for (uint i = 0; i < MaxLight; ++i)
{
m_IdxLighted.Specular[i] = m_FeaturesLighted.CtStartNeLVP + 5 + i;
}
m_IdxLighted.DirOrPos[0] = 9;
for (uint i = 1; i < MaxLight; ++i)
{
m_IdxLighted.DirOrPos[i] = m_FeaturesLighted.CtStartNeLVP + (12 - 1) + i;
}
m_IdxLighted.DiffuseAlpha = m_FeaturesLighted.CtStartNeLVP + 10;
m_IdxLighted.EyePosition = m_FeaturesLighted.CtStartNeLVP + 11;
}
else
{
for (uint i = 0; i < MaxLight; ++i)
{
m_IdxLighted.Specular[i] = ~0;
}
for (uint i = 0; i < MaxLight; ++i)
{
m_IdxLighted.DirOrPos[i] = m_FeaturesLighted.CtStartNeLVP + 5 + i;
}
m_IdxLighted.DiffuseAlpha = m_FeaturesLighted.CtStartNeLVP + 9;
m_IdxLighted.EyePosition = ~0;
}
}
else
{
// Named uniform locations
// TODO_VP_GLSL
// m_IdxLighted.Ambient = getUniformIndex("ambient");
// etc
}
nlassert(m_IdxLighted.Diffuse[0] != ~0);
if (m_FeaturesLighted.SupportSpecular)
{
nlassert(m_IdxLighted.Specular[0] != ~0);
nlassert(m_IdxLighted.EyePosition != ~0);
}
nlassert(m_IdxLighted.DirOrPos[0] != ~0);
nlassert(m_IdxLighted.DiffuseAlpha != ~0);
}
// generates the lighting part of a vertex program, nelvp profile
// ***************************************************************************
std::string CRenderTrav::getLightVPFragment(uint numActivePointLights, uint ctStart, bool supportSpecular, bool normalize)
std::string CRenderTrav::getLightVPFragmentNeLVP(uint numActivePointLights, uint ctStart, bool supportSpecular, bool normalize)
{
string ret;

View file

@ -191,6 +191,8 @@ CScene::CScene(bool bSmallScene) : LightTrav(bSmallScene)
_WaterEnvMap = NULL;
_GlobalSystemTime= 0.0;
_RequestParticlesAnimate = false;
}
// ***************************************************************************
void CScene::release()
@ -377,6 +379,13 @@ void CScene::endPartRender()
// Reset profiling
_NextRenderProfile= false;
IDriver *drv = getDriver();
drv->activeVertexProgram(NULL);
drv->activePixelProgram(NULL);
drv->activeGeometryProgram(NULL);
// Ensure nothing animates on subsequent renders
_EllapsedTime = 0.f;
/*
uint64 total = PSStatsRegisterPSModelObserver +
@ -614,7 +623,11 @@ void CScene::renderPart(UScene::TRenderPart rp, bool doHrcPass)
// loadBalance
LoadBalancingTrav.traverse();
//
_ParticleSystemManager.processAnimate(_EllapsedTime); // deals with permanently animated particle systems
if (_RequestParticlesAnimate)
{
_ParticleSystemManager.processAnimate(_EllapsedTime); // deals with permanently animated particle systems
_RequestParticlesAnimate = false;
}
// Light
LightTrav.traverse();
}
@ -860,6 +873,9 @@ void CScene::animate( TGlobalAnimationTime atTime )
// Rendered part are invalidate
_RenderedPart = UScene::RenderNothing;
// Particles are animated later due to dependencies
_RequestParticlesAnimate = true;
}
@ -1561,6 +1577,8 @@ void CScene::renderOcclusionTestMeshs()
nlassert(RenderTrav.getDriver());
RenderTrav.getDriver()->setupViewport(RenderTrav.getViewport());
RenderTrav.getDriver()->activeVertexProgram(NULL);
RenderTrav.getDriver()->activePixelProgram(NULL);
RenderTrav.getDriver()->activeGeometryProgram(NULL);
IDriver::TPolygonMode oldPolygonMode = RenderTrav.getDriver()->getPolygonMode();
CMaterial m;
m.initUnlit();

View file

@ -1,111 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// 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 <http://www.gnu.org/licenses/>.
#include "std3d.h"
#include "nel/3d/shader.h"
#include "nel/3d/driver.h"
#include "nel/misc/path.h"
#include "nel/misc/file.h"
using namespace std;
using namespace NLMISC;
namespace NL3D
{
// ***************************************************************************
CShader::~CShader()
{
// Must kill the drv mirror of this shader.
_DrvInfo.kill();
}
// ***************************************************************************
CShader::CShader()
{
_ShaderChanged = true;
}
// ***************************************************************************
void CShader::setText (const char *text)
{
_Text = text;
_ShaderChanged = true;
}
// ***************************************************************************
void CShader::setName (const char *name)
{
_Name = name;
_ShaderChanged = true;
}
// ***************************************************************************
bool CShader::loadShaderFile (const char *filename)
{
_Text = "";
// Lookup
string _filename = CPath::lookup(filename, false, true, true);
if (!_filename.empty())
{
// File length
uint size = CFile::getFileSize (_filename);
_Text.reserve (size+1);
try
{
CIFile file;
if (file.open (_filename))
{
// Read it
while (!file.eof ())
{
char line[512];
file.getline (line, 512);
_Text += line;
}
// Set the shader name
_Name = CFile::getFilename (filename);
return true;
}
else
{
nlwarning ("Can't open the file %s for reading", _filename.c_str());
}
}
catch (const Exception &e)
{
nlwarning ("Error while reading %s : %s", _filename.c_str(), e.what());
}
}
return false;
}
// ***************************************************************************
IShaderDrvInfos::~IShaderDrvInfos()
{
_Driver->removeShaderDrvInfoPtr(_DriverIterator);
}
} // NL3D

View file

@ -244,11 +244,12 @@ void CShadowMapManager::addShadowReceiver(CTransform *model)
void CShadowMapManager::renderGenerate(CScene *scene)
{
H_AUTO( NL3D_ShadowManager_Generate );
// Each frame, do a small garbage collector for unused free textures.
garbageShadowTextures(scene);
IDriver *driverForShadowGeneration= scene->getRenderTrav().getAuxDriver();
CSmartPtr<NL3D::ITexture> previousRenderTarget = driverForShadowGeneration->getRenderTarget();
// Init
// ********
@ -488,7 +489,7 @@ void CShadowMapManager::renderGenerate(CScene *scene)
}
// Set default render target
driverForShadowGeneration->setRenderTarget (NULL);
driverForShadowGeneration->setRenderTarget (previousRenderTarget);
// Allow Writing on all.
driverForShadowGeneration->setColorMask(true, true, true, true);

View file

@ -0,0 +1,463 @@
/**
* \file stereo_debugger.cpp
* \brief CStereoDebugger
* \date 2013-07-03 20:17GMT
* \author Jan Boon (Kaetemi)
* CStereoDebugger
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#if !FINAL_VERSION
#include <nel/misc/types_nl.h>
#include <nel/3d/stereo_debugger.h>
// STL includes
// NeL includes
// #include <nel/misc/debug.h>
// Project includes
#include <nel/3d/u_camera.h>
#include <nel/3d/u_driver.h>
#include <nel/3d/material.h>
#include <nel/3d/texture_bloom.h>
#include <nel/3d/texture_user.h>
#include <nel/3d/driver_user.h>
#include <nel/3d/u_texture.h>
using namespace std;
// using namespace NLMISC;
namespace NL3D {
namespace {
const char *a_arbfp1 =
"!!ARBfp1.0\n"
"PARAM c[1] = { { 1, 0, 0.5 } };\n"
"TEMP R0;\n"
"TEMP R1;\n"
"TEMP R2;\n"
"TEX R0, fragment.texcoord[0], texture[0], 2D;\n"
"TEX R1, fragment.texcoord[0], texture[1], 2D;\n"
"ADD R2, R0, -R1;\n"
"ADD R1, R0, R1;\n"
"MUL R1, R1, c[0].z;\n"
"ABS R2, R2;\n"
"CMP R2, -R2, c[0].x, c[0].y;\n"
"ADD_SAT R2.x, R2, R2.y;\n"
"ADD_SAT R2.x, R2, R2.z;\n"
"ADD_SAT R2.x, R2, R2.w;\n"
"ABS R2.x, R2;\n"
"CMP R2.x, -R2, c[0].y, c[0];\n"
"ABS R0.x, R2;\n"
"CMP R2.x, -R0, c[0].y, c[0];\n"
"MOV R0.xzw, R1;\n"
"MAD R0.y, R1, c[0].z, c[0].z;\n"
"CMP R0, -R2.x, R1, R0;\n"
"MAD R1.x, R0, c[0].z, c[0].z;\n"
"CMP result.color.x, -R2, R1, R0;\n"
"MOV result.color.yzw, R0;\n"
"END\n";
const char *a_ps_2_0 =
"ps_2_0\n"
// cgc version 3.1.0013, build date Apr 18 2012
// command line args: -profile ps_2_0
// source file: pp_stereo_debug.cg
//vendor NVIDIA Corporation
//version 3.1.0.13
//profile ps_2_0
//program pp_stereo_debug
//semantic pp_stereo_debug.cTex0 : TEX0
//semantic pp_stereo_debug.cTex1 : TEX1
//var float2 texCoord : $vin.TEXCOORD0 : TEX0 : 0 : 1
//var sampler2D cTex0 : TEX0 : texunit 0 : 1 : 1
//var sampler2D cTex1 : TEX1 : texunit 1 : 2 : 1
//var float4 oCol : $vout.COLOR : COL : 3 : 1
//const c[0] = 0 1 0.5
"dcl_2d s0\n"
"dcl_2d s1\n"
"def c0, 0.00000000, 1.00000000, 0.50000000, 0\n"
"dcl t0.xy\n"
"texld r1, t0, s1\n"
"texld r2, t0, s0\n"
"add r0, r2, -r1\n"
"add r1, r2, r1\n"
"mul r1, r1, c0.z\n"
"abs r0, r0\n"
"cmp r0, -r0, c0.x, c0.y\n"
"add_pp_sat r0.x, r0, r0.y\n"
"add_pp_sat r0.x, r0, r0.z\n"
"add_pp_sat r0.x, r0, r0.w\n"
"abs_pp r0.x, r0\n"
"cmp_pp r0.x, -r0, c0.y, c0\n"
"abs_pp r0.x, r0\n"
"mov r2.xzw, r1\n"
"mad r2.y, r1, c0.z, c0.z\n"
"cmp r2, -r0.x, r1, r2\n"
"mad r1.x, r2, c0.z, c0.z\n"
"mov r0.yzw, r2\n"
"cmp r0.x, -r0, r1, r2\n"
"mov oC0, r0\n";
class CStereoDebuggerFactory : public IStereoDeviceFactory
{
public:
IStereoDisplay *createDevice() const
{
return new CStereoDebugger();
}
};
} /* anonymous namespace */
CStereoDebugger::CStereoDebugger() : m_Driver(NULL), m_Stage(0), m_SubStage(0), m_LeftTexU(NULL), m_RightTexU(NULL), m_PixelProgram(NULL)
{
}
CStereoDebugger::~CStereoDebugger()
{
releaseTextures();
if (!m_Mat.empty())
{
m_Driver->deleteMaterial(m_Mat);
}
delete m_PixelProgram;
m_PixelProgram = NULL;
m_Driver = NULL;
}
/// Sets driver and generates necessary render targets
void CStereoDebugger::setDriver(NL3D::UDriver *driver)
{
nlassert(!m_PixelProgram);
m_Driver = driver;
NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(driver))->getDriver();
if (drvInternal->supportBloomEffect() && drvInternal->supportNonPowerOfTwoTextures())
{
m_PixelProgram = new CPixelProgram();
// arbfp1
{
IProgram::CSource *source = new IProgram::CSource();
source->Features.MaterialFlags = CProgramFeatures::TextureStages;
source->Profile = IProgram::arbfp1;
source->setSourcePtr(a_arbfp1);
m_PixelProgram->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_PixelProgram->addSource(source);
}
if (!drvInternal->compilePixelProgram(m_PixelProgram))
{
nlwarning("No supported pixel program for stereo debugger");
delete m_PixelProgram;
m_PixelProgram = NULL;
}
}
if (m_PixelProgram)
{
initTextures();
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);
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);
m_QuadUV.V3 = CVector(0.f, 1.f, 0.5f);
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);
}
}
void CStereoDebugger::releaseTextures()
{
if (!m_Mat.empty())
{
m_Mat.getObjectPtr()->setTexture(0, NULL);
m_Mat.getObjectPtr()->setTexture(1, NULL);
m_Driver->deleteMaterial(m_Mat);
}
delete m_LeftTexU;
m_LeftTexU = NULL;
m_LeftTex = NULL; // CSmartPtr
delete m_RightTexU;
m_RightTexU = NULL;
m_RightTex = NULL; // CSmartPtr
}
void CStereoDebugger::initTextures()
{
uint32 width, height;
m_Driver->getWindowSize(width, height);
NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(m_Driver))->getDriver();
m_LeftTex = new CTextureBloom();
m_LeftTex->setRenderTarget(true);
m_LeftTex->setReleasable(false);
m_LeftTex->resize(width, height);
m_LeftTex->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff);
m_LeftTex->setWrapS(ITexture::Clamp);
m_LeftTex->setWrapT(ITexture::Clamp);
drvInternal->setupTexture(*m_LeftTex);
m_LeftTexU = new CTextureUser(m_LeftTex);
nlassert(!drvInternal->isTextureRectangle(m_LeftTex)); // not allowed
m_RightTex = new CTextureBloom();
m_RightTex->setRenderTarget(true);
m_RightTex->setReleasable(false);
m_RightTex->resize(width, height);
m_RightTex->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff);
m_RightTex->setWrapS(ITexture::Clamp);
m_RightTex->setWrapT(ITexture::Clamp);
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)
{
uint32 width, height;
m_Driver->getWindowSize(width, height);
if (m_LeftTex->getWidth() != width
|| m_RightTex->getWidth() != width
|| m_LeftTex->getHeight() != height
|| m_RightTex->getHeight() != height)
{
nldebug("Rebuild textures");
releaseTextures();
initTextures();
setTextures();
}
}
}
/// Gets the required screen resolution for this device
bool CStereoDebugger::getScreenResolution(uint &width, uint &height)
{
return false;
}
/// Set latest camera position etcetera
void CStereoDebugger::updateCamera(uint cid, const NL3D::UCamera *camera)
{
m_Frustum[cid] = camera->getFrustum();
}
/// Get the frustum to use for clipping
void CStereoDebugger::getClippingFrustum(uint cid, NL3D::UCamera *camera) const
{
// do nothing
}
/// Is there a next pass
bool CStereoDebugger::nextPass()
{
if (m_Driver->getPolygonMode() == UDriver::Filled)
{
switch (m_Stage)
{
case 0:
++m_Stage;
m_SubStage = 0;
return true;
case 1:
++m_Stage;
m_SubStage = 0;
return true;
case 2:
++m_Stage;
m_SubStage = 0;
return true;
case 3:
m_Stage = 0;
m_SubStage = 0;
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;
}
}
return false;
}
/// Gets the current viewport
const NL3D::CViewport &CStereoDebugger::getCurrentViewport() const
{
if (m_Stage % 2) return m_LeftViewport;
else return m_RightViewport;
}
/// Gets the current camera frustum
const NL3D::CFrustum &CStereoDebugger::getCurrentFrustum(uint cid) const
{
return m_Frustum[cid];
}
/// Gets the current camera frustum
void CStereoDebugger::getCurrentFrustum(uint cid, NL3D::UCamera *camera) const
{
// do nothing
}
/// Gets the current camera matrix
void CStereoDebugger::getCurrentMatrix(uint cid, NL3D::UCamera *camera) const
{
// do nothing
}
/// At the start of a new render target
bool CStereoDebugger::wantClear()
{
m_SubStage = 1;
return m_Stage != 3;
}
/// The 3D scene
bool CStereoDebugger::wantScene()
{
m_SubStage = 2;
return m_Stage != 3;
}
/// Interface within the 3D scene
bool CStereoDebugger::wantInterface3D()
{
m_SubStage = 3;
return m_Stage == 3;
}
/// 2D Interface
bool CStereoDebugger::wantInterface2D()
{
m_SubStage = 4;
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_Stage % 2) static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_RightTexU, 0, 0, 0, 0);
else static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_LeftTexU, 0, 0, 0, 0);
return true;
}
return false;
}
/// Returns true if a render target was fully drawn, always false if not using render targets
bool CStereoDebugger::endRenderTarget()
{
if (m_Stage != 3 && m_Driver && (m_Driver->getPolygonMode() == UDriver::Filled))
{
CTextureUser cu;
(static_cast<CDriverUser *>(m_Driver))->setRenderTarget(cu);
bool fogEnabled = m_Driver->fogEnabled();
m_Driver->enableFog(false);
m_Driver->setMatrixMode2D11();
CViewport vp = CViewport();
m_Driver->setViewport(vp);
uint32 width, height;
NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(m_Driver))->getDriver();
NL3D::CMaterial *mat = m_Mat.getObjectPtr();
mat->setTexture(0, m_LeftTex);
mat->setTexture(1, m_RightTex);
drvInternal->activePixelProgram(m_PixelProgram);
m_Driver->drawQuad(m_QuadUV, m_Mat);
drvInternal->activePixelProgram(NULL);
m_Driver->enableFog(fogEnabled);
return true;
}
return false;
}
void CStereoDebugger::listDevices(std::vector<CStereoDeviceInfo> &devicesOut)
{
CStereoDeviceInfo devInfo;
devInfo.Factory = new CStereoDebuggerFactory();
devInfo.Library = CStereoDeviceInfo::NeL3D;
devInfo.Class = CStereoDeviceInfo::StereoDisplay;
devInfo.Manufacturer = "NeL";
devInfo.ProductName = "Stereo Debugger";
devInfo.Serial = "NL-3D-DEBUG";
devicesOut.push_back(devInfo);
}
} /* namespace NL3D */
#endif /* #if !FINAL_VERSION */
/* end of file */

View file

@ -0,0 +1,112 @@
/**
* \file stereo_display.cpp
* \brief IStereoDisplay
* \date 2013-06-27 16:29GMT
* \author Jan Boon (Kaetemi)
* IStereoDisplay
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#include <nel/misc/types_nl.h>
#include <nel/3d/stereo_display.h>
// STL includes
// NeL includes
// #include <nel/misc/debug.h>
// Project includes
#include <nel/3d/stereo_ovr.h>
#include <nel/3d/stereo_libvr.h>
#include <nel/3d/stereo_debugger.h>
using namespace std;
// using namespace NLMISC;
namespace NL3D {
IStereoDisplay::IStereoDisplay()
{
}
IStereoDisplay::~IStereoDisplay()
{
}
const char *IStereoDisplay::getLibraryName(CStereoDeviceInfo::TStereoDeviceLibrary library)
{
static const char *nel3dName = "NeL 3D";
static const char *ovrName = "Oculus SDK";
static const char *libvrName = "LibVR";
static const char *openhmdName = "OpenHMD";
switch (library)
{
case CStereoDeviceInfo::NeL3D:
return nel3dName;
case CStereoDeviceInfo::OVR:
return ovrName;
case CStereoDeviceInfo::LibVR:
return libvrName;
case CStereoDeviceInfo::OpenHMD:
return openhmdName;
}
nlerror("Invalid device library specified");
return "<InvalidDeviceLibrary>";
}
void IStereoDisplay::listDevices(std::vector<CStereoDeviceInfo> &devicesOut)
{
#ifdef HAVE_LIBOVR
CStereoOVR::listDevices(devicesOut);
#endif
#ifdef HAVE_LIBVR
CStereoLibVR::listDevices(devicesOut);
#endif
#if !FINAL_VERSION
CStereoDebugger::listDevices(devicesOut);
#endif
}
IStereoDisplay *IStereoDisplay::createDevice(const CStereoDeviceInfo &deviceInfo)
{
return deviceInfo.Factory->createDevice();
}
void IStereoDisplay::releaseUnusedLibraries()
{
#ifdef HAVE_LIBOVR
if (!CStereoOVR::isLibraryInUse())
CStereoOVR::releaseLibrary();
#endif
}
void IStereoDisplay::releaseAllLibraries()
{
#ifdef HAVE_LIBOVR
CStereoOVR::releaseLibrary();
#endif
}
} /* namespace NL3D */
/* end of file */

View file

@ -0,0 +1,55 @@
/**
* \file stereo_hmd.cpp
* \brief IStereoHMD
* \date 2013-06-27 16:30GMT
* \author Jan Boon (Kaetemi)
* IStereoHMD
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#include <nel/misc/types_nl.h>
#include <nel/3d/stereo_hmd.h>
// STL includes
// NeL includes
// #include <nel/misc/debug.h>
// Project includes
using namespace std;
// using namespace NLMISC;
namespace NL3D {
IStereoHMD::IStereoHMD()
{
}
IStereoHMD::~IStereoHMD()
{
}
} /* namespace NL3D */
/* end of file */

View file

@ -0,0 +1,642 @@
/**
* \file stereo_libvr.cpp
* \brief CStereoLibVR
* \date 2013-08-19 19:17MT
* \author Thibaut Girka (ThibG)
* CStereoLibVR
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_LIBVR
#include <nel/misc/types_nl.h>
#include <nel/misc/time_nl.h>
#include <nel/3d/stereo_libvr.h>
// STL includes
#include <sstream>
// External includes
extern "C" {
#include <hmd.h>
}
// NeL includes
// #include <nel/misc/debug.h>
#include <nel/3d/u_camera.h>
#include <nel/3d/u_driver.h>
#include <nel/3d/material.h>
#include <nel/3d/texture_bloom.h>
#include <nel/3d/texture_user.h>
#include <nel/3d/driver_user.h>
#include <nel/3d/u_texture.h>
// Project includes
using namespace std;
// using namespace NLMISC;
namespace NL3D {
extern const char *g_StereoOVR_fp40; //TODO: what?
extern const char *g_StereoOVR_arbfp1; //TODO: what?
extern const char *g_StereoOVR_ps_2_0; //TODO: what?
namespace {
sint s_DeviceCounter = 0;
};
class CStereoLibVRDeviceHandle : public IStereoDeviceFactory
{
public:
// fixme: virtual destructor???
IStereoDisplay *createDevice() const
{
CStereoLibVR *stereo = new CStereoLibVR(this);
if (stereo->isDeviceCreated())
return stereo;
delete stereo;
return NULL;
}
};
class CStereoLibVRDevicePtr
{
public:
struct hmd *HMDDevice;
struct display_info HMDInfo;
float InterpupillaryDistance;
};
CStereoLibVR::CStereoLibVR(const CStereoLibVRDeviceHandle *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)
{
struct stereo_config st_conf;
++s_DeviceCounter;
// For now, LibVR doesn't support multiple devices...
m_DevicePtr = new CStereoLibVRDevicePtr();
m_DevicePtr->HMDDevice = hmd_open_first(0);
m_DevicePtr->InterpupillaryDistance = 0.0647; //TODO
if (m_DevicePtr->HMDDevice)
{
hmd_get_display_info(m_DevicePtr->HMDDevice, &m_DevicePtr->HMDInfo);
hmd_get_stereo_config(m_DevicePtr->HMDDevice, &st_conf);
nldebug("LibVR: HScreenSize: %f, VScreenSize: %f", m_DevicePtr->HMDInfo.h_screen_size, m_DevicePtr->HMDInfo.v_screen_size);
nldebug("LibVR: VScreenCenter: %f", m_DevicePtr->HMDInfo.v_center);
nldebug("LibVR: EyeToScreenDistance: %f", m_DevicePtr->HMDInfo.eye_to_screen[0]);
nldebug("LibVR: LensSeparationDistance: %f", m_DevicePtr->HMDInfo.lens_separation);
nldebug("LibVR: HResolution: %i, VResolution: %i", m_DevicePtr->HMDInfo.h_resolution, m_DevicePtr->HMDInfo.v_resolution);
nldebug("LibVR: DistortionK[0]: %f, DistortionK[1]: %f", m_DevicePtr->HMDInfo.distortion_k[0], m_DevicePtr->HMDInfo.distortion_k[1]);
nldebug("LibVR: DistortionK[2]: %f, DistortionK[3]: %f", m_DevicePtr->HMDInfo.distortion_k[2], m_DevicePtr->HMDInfo.distortion_k[3]);
nldebug("LibVR: Scale: %f", st_conf.distort.scale);
m_LeftViewport.init(0.f, 0.f, 0.5f, 1.0f);
m_RightViewport.init(0.5f, 0.f, 0.5f, 1.0f);
}
}
CStereoLibVR::~CStereoLibVR()
{
if (!m_BarrelMat.empty())
{
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;
m_Driver = NULL;
if (m_DevicePtr->HMDDevice)
hmd_close(m_DevicePtr->HMDDevice);
delete m_DevicePtr;
m_DevicePtr = NULL;
--s_DeviceCounter;
}
void CStereoLibVR::setDriver(NL3D::UDriver *driver)
{
nlassert(!m_PixelProgram);
NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(driver))->getDriver();
if (drvInternal->supportPixelProgram(CPixelProgram::fp40) && drvInternal->supportBloomEffect() && drvInternal->supportNonPowerOfTwoTextures())
{
nldebug("VR: fp40");
m_PixelProgram = new CPixelProgram(g_StereoOVR_fp40);
}
else if (drvInternal->supportPixelProgram(CPixelProgram::arbfp1) && drvInternal->supportBloomEffect() && drvInternal->supportNonPowerOfTwoTextures())
{
nldebug("VR: arbfp1");
m_PixelProgram = new CPixelProgram(g_StereoOVR_arbfp1);
}
else if (drvInternal->supportPixelProgram(CPixelProgram::ps_2_0))
{
nldebug("VR: ps_2_0");
m_PixelProgram = new CPixelProgram(g_StereoOVR_ps_2_0);
}
if (m_PixelProgram)
{
m_Driver = driver;
m_BarrelTex = new CTextureBloom(); // lol bloom
m_BarrelTex->setRenderTarget(true);
m_BarrelTex->setReleasable(false);
m_BarrelTex->resize(m_DevicePtr->HMDInfo.h_resolution, m_DevicePtr->HMDInfo.v_resolution);
m_BarrelTex->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff);
m_BarrelTex->setWrapS(ITexture::Clamp);
m_BarrelTex->setWrapT(ITexture::Clamp);
drvInternal->setupTexture(*m_BarrelTex);
m_BarrelTexU = new CTextureUser(m_BarrelTex);
m_BarrelMat = m_Driver->createMaterial();
m_BarrelMat.initUnlit();
m_BarrelMat.setColor(CRGBA::White);
m_BarrelMat.setBlend (false);
m_BarrelMat.setAlphaTest (false);
NL3D::CMaterial *barrelMat = m_BarrelMat.getObjectPtr();
barrelMat->setShader(NL3D::CMaterial::PostProcessing);
barrelMat->setBlendFunc(CMaterial::one, CMaterial::zero);
barrelMat->setZWrite(false);
barrelMat->setZFunc(CMaterial::always);
barrelMat->setDoubleSided(true);
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);
m_BarrelQuadLeft.V2 = CVector(0.5f, 1.f, 0.5f);
m_BarrelQuadLeft.V3 = CVector(0.f, 1.f, 0.5f);
m_BarrelQuadRight.V0 = CVector(0.5f, 0.f, 0.5f);
m_BarrelQuadRight.V1 = CVector(1.f, 0.f, 0.5f);
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
m_BarrelQuadLeft.Uv0 = CUV(0.f, 0.f);
m_BarrelQuadLeft.Uv1 = CUV(0.5f, 0.f);
m_BarrelQuadLeft.Uv2 = CUV(0.5f, 1.f);
m_BarrelQuadLeft.Uv3 = CUV(0.f, 1.f);
m_BarrelQuadRight.Uv0 = CUV(0.5f, 0.f);
m_BarrelQuadRight.Uv1 = CUV(1.f, 0.f);
m_BarrelQuadRight.Uv2 = CUV(1.f, 1.f);
m_BarrelQuadRight.Uv3 = CUV(0.5f, 1.f);
}
else
{
nlwarning("VR: No pixel program support");
}
}
bool CStereoLibVR::getScreenResolution(uint &width, uint &height)
{
width = m_DevicePtr->HMDInfo.h_resolution;
height = m_DevicePtr->HMDInfo.v_resolution;
return true;
}
void CStereoLibVR::initCamera(uint cid, const NL3D::UCamera *camera)
{
struct stereo_config st_conf;
hmd_get_stereo_config(m_DevicePtr->HMDDevice, &st_conf);
float ar = st_conf.proj.aspect_ratio;
float fov = st_conf.proj.yfov;
m_LeftFrustum[cid].initPerspective(fov, ar, camera->getFrustum().Near, camera->getFrustum().Far);
m_RightFrustum[cid] = m_LeftFrustum[cid];
float projectionCenterOffset = st_conf.proj.projection_offset * 0.5 * (m_LeftFrustum[cid].Right - m_LeftFrustum[cid].Left);
nldebug("LibVR: projectionCenterOffset = %f", projectionCenterOffset);
m_LeftFrustum[cid].Left -= projectionCenterOffset;
m_LeftFrustum[cid].Right -= projectionCenterOffset;
m_RightFrustum[cid].Left += projectionCenterOffset;
m_RightFrustum[cid].Right += projectionCenterOffset;
// TODO: Clipping frustum should also take into account the IPD
m_ClippingFrustum[cid] = m_LeftFrustum[cid];
m_ClippingFrustum[cid].Left = min(m_LeftFrustum[cid].Left, m_RightFrustum[cid].Left);
m_ClippingFrustum[cid].Right = max(m_LeftFrustum[cid].Right, m_RightFrustum[cid].Right);
}
/// Get the frustum to use for clipping
void CStereoLibVR::getClippingFrustum(uint cid, NL3D::UCamera *camera) const
{
camera->setFrustum(m_ClippingFrustum[cid]);
}
void CStereoLibVR::updateCamera(uint cid, const NL3D::UCamera *camera)
{
if (camera->getFrustum().Near != m_LeftFrustum[cid].Near
|| camera->getFrustum().Far != m_LeftFrustum[cid].Far)
CStereoLibVR::initCamera(cid, camera);
m_CameraMatrix[cid] = camera->getMatrix();
}
bool CStereoLibVR::nextPass()
{
// Do not allow weird stuff.
uint32 width, height;
m_Driver->getWindowSize(width, height);
nlassert(width == m_DevicePtr->HMDInfo.h_resolution);
nlassert(height == m_DevicePtr->HMDInfo.v_resolution);
if (m_Driver->getPolygonMode() == UDriver::Filled)
{
switch (m_Stage)
{
case 0:
++m_Stage;
m_SubStage = 0;
// stage 1:
// (initBloom)
// clear buffer
// draw scene left
return true;
case 1:
++m_Stage;
m_SubStage = 0;
// stage 2:
// draw scene right
return true;
case 2:
++m_Stage;
m_SubStage = 0;
// stage 3:
// (endBloom)
// draw interface 3d left
return true;
case 3:
++m_Stage;
m_SubStage = 0;
// stage 4:
// draw interface 3d right
return true;
case 4:
++m_Stage;
m_SubStage = 0;
// stage 5:
// (endInterfacesDisplayBloom)
// draw interface 2d left
return true;
case 5:
++m_Stage;
m_SubStage = 0;
// stage 6:
// 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 &CStereoLibVR::getCurrentViewport() const
{
if (m_Stage % 2) return m_LeftViewport;
else return m_RightViewport;
}
const NL3D::CFrustum &CStereoLibVR::getCurrentFrustum(uint cid) const
{
if (m_Stage % 2) return m_LeftFrustum[cid];
else return m_RightFrustum[cid];
}
void CStereoLibVR::getCurrentFrustum(uint cid, NL3D::UCamera *camera) const
{
if (m_Stage % 2) camera->setFrustum(m_LeftFrustum[cid]);
else camera->setFrustum(m_RightFrustum[cid]);
}
void CStereoLibVR::getCurrentMatrix(uint cid, NL3D::UCamera *camera) const
{
CMatrix translate;
if (m_Stage % 2) translate.translate(CVector((m_DevicePtr->InterpupillaryDistance * m_Scale) * -0.5f, 0.f, 0.f));
else translate.translate(CVector((m_DevicePtr->InterpupillaryDistance * m_Scale) * 0.5f, 0.f, 0.f));
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 CStereoLibVR::wantClear()
{
switch (m_Stage)
{
case 1:
m_SubStage = 1;
return true;
}
return m_Driver->getPolygonMode() != UDriver::Filled;
}
bool CStereoLibVR::wantScene()
{
switch (m_Stage)
{
case 1:
case 2:
m_SubStage = 2;
return true;
}
return m_Driver->getPolygonMode() != UDriver::Filled;
}
bool CStereoLibVR::wantInterface3D()
{
switch (m_Stage)
{
case 3:
case 4:
m_SubStage = 3;
return true;
}
return m_Driver->getPolygonMode() != UDriver::Filled;
}
bool CStereoLibVR::wantInterface2D()
{
switch (m_Stage)
{
case 5:
case 6:
m_SubStage = 4;
return true;
}
return m_Driver->getPolygonMode() != UDriver::Filled;
}
/// Returns non-NULL if a new render target was set
bool CStereoLibVR::beginRenderTarget()
{
// render target always set before driver clear
// nlassert(m_SubStage <= 1);
if (m_Driver && m_Stage == 1 && (m_Driver->getPolygonMode() == UDriver::Filled))
{
static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_BarrelTexU, 0, 0, 0, 0);
return true;
}
return false;
}
/// Returns true if a render target was fully drawn
bool CStereoLibVR::endRenderTarget()
{
// after rendering of course
// nlassert(m_SubStage > 1);
if (m_Driver && m_Stage == 6 && (m_Driver->getPolygonMode() == UDriver::Filled)) // set to 4 to turn off distortion of 2d gui
{
struct stereo_config st_conf;
hmd_get_stereo_config(m_DevicePtr->HMDDevice, &st_conf);
CTextureUser cu;
(static_cast<CDriverUser *>(m_Driver))->setRenderTarget(cu);
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<CDriverUser *>(m_Driver))->getDriver();
NL3D::CMaterial *barrelMat = m_BarrelMat.getObjectPtr();
barrelMat->setTexture(0, m_BarrelTex);
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);
//TODO: stereo_config stuff
float lensViewportShift = st_conf.proj.projection_offset;
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 / st_conf.distort.scale);
float scaleY = (h / 2 / st_conf.distort.scale);
float scaleInX = (2 / w);
float scaleInY = (2 / h);
drvInternal->setPixelProgramConstant(0, lensCenterX, lensCenterY, 0.f, 0.f);
drvInternal->setPixelProgramConstant(1, screenCenterX, screenCenterY, 0.f, 0.f);
drvInternal->setPixelProgramConstant(2, scaleX, scaleY, 0.f, 0.f);
drvInternal->setPixelProgramConstant(3, scaleInX, scaleInY, 0.f, 0.f);
drvInternal->setPixelProgramConstant(4, 1, st_conf.distort.distortion_k);
m_Driver->drawQuad(m_BarrelQuadLeft, m_BarrelMat);
x = w;
lensCenterX = x + (w - lensViewportShift * 0.5f) * 0.5f;
screenCenterX = x + w * 0.5f;
drvInternal->setPixelProgramConstant(0, lensCenterX, lensCenterY, 0.f, 0.f);
drvInternal->setPixelProgramConstant(1, screenCenterX, screenCenterY, 0.f, 0.f);
m_Driver->drawQuad(m_BarrelQuadRight, m_BarrelMat);
drvInternal->activePixelProgram(NULL);
m_Driver->enableFog(fogEnabled);
return true;
}
return false;
}
NLMISC::CQuat CStereoLibVR::getOrientation() const
{
if (m_OrientationCached)
return m_OrientationCache;
unsigned int t = NLMISC::CTime::getLocalTime();
hmd_update(m_DevicePtr->HMDDevice, &t);
float quat[4];
hmd_get_rotation(m_DevicePtr->HMDDevice, quat);
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(quat[1], quat[2], quat[3], quat[0]));
NLMISC::CMatrix matr;
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;
}
/// Get GUI shift
void CStereoLibVR::getInterface2DShift(uint cid, float &x, float &y, float distance) const
{
#if 0
// todo: take into account m_EyePosition
NLMISC::CVector vector = CVector(0.f, -distance, 0.f);
NLMISC::CQuat rot = getOrientation();
rot.invert();
NLMISC::CMatrix mat;
mat.rotate(rot);
//if (m_Stage % 2) mat.translate(CVector(m_DevicePtr->HMDInfo.InterpupillaryDistance * -0.5f, 0.f, 0.f));
//else mat.translate(CVector(m_DevicePtr->HMDInfo.InterpupillaryDistance * 0.5f, 0.f, 0.f));
mat.translate(vector);
CVector proj = CStereoOVR::getCurrentFrustum(cid).project(mat.getPos());
NLMISC::CVector ipd;
if (m_Stage % 2) ipd = CVector(m_DevicePtr->HMDInfo.InterpupillaryDistance * -0.5f, 0.f, 0.f);
else ipd = CVector(m_DevicePtr->HMDInfo.InterpupillaryDistance * 0.5f, 0.f, 0.f);
CVector projipd = CStereoOVR::getCurrentFrustum(cid).project(vector + ipd);
CVector projvec = CStereoOVR::getCurrentFrustum(cid).project(vector);
x = (proj.x + projipd.x - projvec.x - 0.5f);
y = (proj.y + projipd.y - projvec.y - 0.5f);
#elif 1
// Alternative method
// todo: take into account m_EyePosition
NLMISC::CVector vec = CVector(0.f, -distance, 0.f);
NLMISC::CVector ipd;
if (m_Stage % 2) ipd = CVector((m_DevicePtr->InterpupillaryDistance * m_Scale) * -0.5f, 0.f, 0.f);
else ipd = CVector((m_DevicePtr->InterpupillaryDistance * m_Scale) * 0.5f, 0.f, 0.f);
NLMISC::CQuat rot = getOrientation();
NLMISC::CQuat modrot = NLMISC::CQuat(CVector(0.f, 1.f, 0.f), NLMISC::Pi);
rot = rot * modrot;
float p = NLMISC::Pi + atan2f(2.0f * ((rot.x * rot.y) + (rot.z * rot.w)), 1.0f - 2.0f * ((rot.y * rot.y) + (rot.w * rot.w)));
if (p > NLMISC::Pi) p -= NLMISC::Pi * 2.0f;
float t = -atan2f(2.0f * ((rot.x * rot.w) + (rot.y * rot.z)), 1.0f - 2.0f * ((rot.z * rot.z) + (rot.w * rot.w)));// // asinf(2.0f * ((rot.x * rot.z) - (rot.w * rot.y)));
CVector rotshift = CVector(p, 0.f, t) * -distance;
CVector proj = CStereoLibVR::getCurrentFrustum(cid).project(vec + ipd + rotshift);
x = (proj.x - 0.5f);
y = (proj.y - 0.5f);
#endif
}
void CStereoLibVR::setEyePosition(const NLMISC::CVector &v)
{
m_EyePosition = v;
}
const NLMISC::CVector &CStereoLibVR::getEyePosition() const
{
return m_EyePosition;
}
void CStereoLibVR::setScale(float s)
{
m_EyePosition = m_EyePosition * (s / m_Scale);
m_Scale = s;
}
void CStereoLibVR::listDevices(std::vector<CStereoDeviceInfo> &devicesOut)
{
// For now, LibVR doesn't support multiple devices
struct hmd *hmd = hmd_open_first(0);
if (hmd)
{
CStereoDeviceInfo deviceInfoOut;
CStereoLibVRDeviceHandle *handle = new CStereoLibVRDeviceHandle();
deviceInfoOut.Factory = static_cast<IStereoDeviceFactory *>(handle);
deviceInfoOut.Class = CStereoDeviceInfo::StereoHMD;
deviceInfoOut.Library = CStereoDeviceInfo::LibVR;
//TODO: manufacturer, produc name
//TODO: serial
devicesOut.push_back(deviceInfoOut);
hmd_close(hmd);
}
}
bool CStereoLibVR::isLibraryInUse()
{
nlassert(s_DeviceCounter >= 0);
return s_DeviceCounter > 0;
}
void CStereoLibVR::releaseLibrary()
{
nlassert(s_DeviceCounter == 0);
}
bool CStereoLibVR::isDeviceCreated()
{
return m_DevicePtr->HMDDevice != NULL;
}
} /* namespace NL3D */
#endif /* HAVE_LIBVR */
/* end of file */

View file

@ -0,0 +1,850 @@
/**
* \file stereo_ovr.cpp
* \brief CStereoOVR
* \date 2013-06-25 22:22GMT
* \author Jan Boon (Kaetemi)
* CStereoOVR
*/
/*
* 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
* <http://www.gnu.org/licenses/>.
*
* 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 <nel/misc/types_nl.h>
#include <nel/3d/stereo_ovr.h>
// STL includes
#include <sstream>
// External includes
#include <OVR.h>
// NeL includes
// #include <nel/misc/debug.h>
#include <nel/3d/u_camera.h>
#include <nel/3d/u_driver.h>
#include <nel/3d/material.h>
#include <nel/3d/texture_bloom.h>
#include <nel/3d/texture_user.h>
#include <nel/3d/driver_user.h>
#include <nel/3d/u_texture.h>
// Project includes
using namespace std;
// using namespace NLMISC;
namespace NL3D {
extern const char *g_StereoOVR_fp40;
extern const char *g_StereoOVR_arbfp1;
extern const char *g_StereoOVR_ps_2_0;
extern const char *g_StereoOVR_glsl330f;
namespace {
class CStereoOVRLog : public OVR::Log
{
public:
CStereoOVRLog(unsigned logMask = OVR::LogMask_All) : OVR::Log(logMask)
{
}
virtual void LogMessageVarg(OVR::LogMessageType messageType, const char* fmt, va_list argList)
{
if (NLMISC::INelContext::isContextInitialised())
{
char buffer[MaxLogBufferMessageSize];
FormatLog(buffer, MaxLogBufferMessageSize, messageType, fmt, argList);
if (IsDebugMessage(messageType))
NLMISC::INelContext::getInstance().getDebugLog()->displayNL("OVR: %s", buffer);
else
NLMISC::INelContext::getInstance().getInfoLog()->displayNL("OVR: %s", buffer);
}
}
};
CStereoOVRLog *s_StereoOVRLog = NULL;
OVR::Ptr<OVR::DeviceManager> s_DeviceManager;
class CStereoOVRSystem
{
public:
~CStereoOVRSystem()
{
Release();
}
void Init()
{
if (!s_StereoOVRLog)
{
nldebug("Initialize OVR");
s_StereoOVRLog = new CStereoOVRLog();
}
if (!OVR::System::IsInitialized())
OVR::System::Init(s_StereoOVRLog);
if (!s_DeviceManager)
s_DeviceManager = OVR::DeviceManager::Create();
}
void Release()
{
if (s_DeviceManager)
{
nldebug("Release OVR");
s_DeviceManager->Release();
}
s_DeviceManager.Clear();
if (OVR::System::IsInitialized())
OVR::System::Destroy();
if (s_StereoOVRLog)
nldebug("Release OVR Ok");
delete s_StereoOVRLog;
s_StereoOVRLog = NULL;
}
};
CStereoOVRSystem s_StereoOVRSystem;
sint s_DeviceCounter = 0;
}
class CStereoOVRDeviceHandle : public IStereoDeviceFactory
{
public:
// fixme: virtual destructor???
OVR::DeviceEnumerator<OVR::HMDDevice> DeviceHandle;
IStereoDisplay *createDevice() const
{
CStereoOVR *stereo = new CStereoOVR(this);
if (stereo->isDeviceCreated())
return stereo;
delete stereo;
return NULL;
}
};
class CStereoOVRDevicePtr
{
public:
OVR::Ptr<OVR::HMDDevice> HMDDevice;
OVR::Ptr<OVR::SensorDevice> SensorDevice;
OVR::SensorFusion SensorFusion;
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)
{
++s_DeviceCounter;
m_DevicePtr = new CStereoOVRDevicePtr();
OVR::DeviceEnumerator<OVR::HMDDevice> dh = handle->DeviceHandle;
m_DevicePtr->HMDDevice = dh.CreateDevice();
if (m_DevicePtr->HMDDevice)
{
m_DevicePtr->HMDDevice->GetDeviceInfo(&m_DevicePtr->HMDInfo);
nldebug("OVR: HScreenSize: %f, VScreenSize: %f", m_DevicePtr->HMDInfo.HScreenSize, m_DevicePtr->HMDInfo.VScreenSize);
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: HResolution: %i, VResolution: %i", m_DevicePtr->HMDInfo.HResolution, m_DevicePtr->HMDInfo.VResolution);
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]);
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 160 NL3D::CStereoOVR::CStereoOVR : OVR: HScreenSize: 0.149760, VScreenSize: 0.093600
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 161 NL3D::CStereoOVR::CStereoOVR : OVR: VScreenCenter: 0.046800
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 162 NL3D::CStereoOVR::CStereoOVR : OVR: EyeToScreenDistance: 0.041000
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 163 NL3D::CStereoOVR::CStereoOVR : OVR: LensSeparationDistance: 0.063500
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 164 NL3D::CStereoOVR::CStereoOVR : OVR: InterpupillaryDistance: 0.064000
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 165 NL3D::CStereoOVR::CStereoOVR : OVR: HResolution: 1280, VResolution: 800
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 166 NL3D::CStereoOVR::CStereoOVR : OVR: DistortionK[0]: 1.000000, DistortionK[1]: 0.220000
//2013/06/26 05:31:51 DBG 17a0 snowballs_client.exe stereo_ovr.cpp 167 NL3D::CStereoOVR::CStereoOVR : OVR: DistortionK[2]: 0.240000, DistortionK[3]: 0.000000
m_DevicePtr->SensorDevice = m_DevicePtr->HMDDevice->GetSensor();
m_DevicePtr->SensorFusion.AttachToSensor(m_DevicePtr->SensorDevice);
m_DevicePtr->SensorFusion.SetGravityEnabled(true);
m_DevicePtr->SensorFusion.SetPredictionEnabled(true);
m_DevicePtr->SensorFusion.SetYawCorrectionEnabled(true);
m_LeftViewport.init(0.f, 0.f, 0.5f, 1.0f);
m_RightViewport.init(0.5f, 0.f, 0.5f, 1.0f);
}
}
CStereoOVR::~CStereoOVR()
{
if (!m_BarrelMat.empty())
{
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;
m_Driver = NULL;
if (m_DevicePtr->SensorDevice)
m_DevicePtr->SensorDevice->Release();
m_DevicePtr->SensorDevice.Clear();
if (m_DevicePtr->HMDDevice)
m_DevicePtr->HMDDevice->Release();
m_DevicePtr->HMDDevice.Clear();
delete m_DevicePtr;
m_DevicePtr = NULL;
--s_DeviceCounter;
}
class CPixelProgramOVR : public CPixelProgram
{
public:
struct COVRIndices
{
uint LensCenter;
uint ScreenCenter;
uint Scale;
uint ScaleIn;
uint HmdWarpParam;
};
CPixelProgramOVR()
{
{
CSource *source = new CSource();
source->Profile = glsl330f;
source->Features.MaterialFlags = CProgramFeatures::TextureStages;
source->setSourcePtr(g_StereoOVR_glsl330f);
addSource(source);
}
{
CSource *source = new CSource();
source->Profile = fp40;
source->Features.MaterialFlags = CProgramFeatures::TextureStages;
source->setSourcePtr(g_StereoOVR_fp40);
source->ParamIndices["cLensCenter"] = 0;
source->ParamIndices["cScreenCenter"] = 1;
source->ParamIndices["cScale"] = 2;
source->ParamIndices["cScaleIn"] = 3;
source->ParamIndices["cHmdWarpParam"] = 4;
addSource(source);
}
{
CSource *source = new CSource();
source->Profile = arbfp1;
source->Features.MaterialFlags = CProgramFeatures::TextureStages;
source->setSourcePtr(g_StereoOVR_arbfp1);
source->ParamIndices["cLensCenter"] = 0;
source->ParamIndices["cScreenCenter"] = 1;
source->ParamIndices["cScale"] = 2;
source->ParamIndices["cScaleIn"] = 3;
source->ParamIndices["cHmdWarpParam"] = 4;
addSource(source);
}
{
CSource *source = new CSource();
source->Profile = ps_2_0;
source->Features.MaterialFlags = CProgramFeatures::TextureStages;
source->setSourcePtr(g_StereoOVR_ps_2_0);
source->ParamIndices["cLensCenter"] = 0;
source->ParamIndices["cScreenCenter"] = 1;
source->ParamIndices["cScale"] = 2;
source->ParamIndices["cScaleIn"] = 3;
source->ParamIndices["cHmdWarpParam"] = 4;
addSource(source);
}
}
virtual ~CPixelProgramOVR()
{
}
virtual void buildInfo()
{
CPixelProgram::buildInfo();
m_OVRIndices.LensCenter = getUniformIndex("cLensCenter");
nlassert(m_OVRIndices.LensCenter != ~0);
m_OVRIndices.ScreenCenter = getUniformIndex("cScreenCenter");
nlassert(m_OVRIndices.ScreenCenter != ~0);
m_OVRIndices.Scale = getUniformIndex("cScale");
nlassert(m_OVRIndices.Scale != ~0);
m_OVRIndices.ScaleIn = getUniformIndex("cScaleIn");
nlassert(m_OVRIndices.ScaleIn != ~0);
m_OVRIndices.HmdWarpParam = getUniformIndex("cHmdWarpParam");
nlassert(m_OVRIndices.HmdWarpParam != ~0);
}
inline const COVRIndices &ovrIndices() { return m_OVRIndices; }
private:
COVRIndices m_OVRIndices;
};
void CStereoOVR::setDriver(NL3D::UDriver *driver)
{
nlassert(!m_PixelProgram);
NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(driver))->getDriver();
if (drvInternal->supportBloomEffect() && drvInternal->supportNonPowerOfTwoTextures())
{
m_PixelProgram = new CPixelProgramOVR();
if (!drvInternal->compilePixelProgram(m_PixelProgram))
{
m_PixelProgram.kill();
}
}
if (m_PixelProgram)
{
m_Driver = driver;
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);
m_BarrelTex->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff);
m_BarrelTex->setWrapS(ITexture::Clamp);
m_BarrelTex->setWrapT(ITexture::Clamp);
drvInternal->setupTexture(*m_BarrelTex);
m_BarrelTexU = new CTextureUser(m_BarrelTex);
m_BarrelMat = m_Driver->createMaterial();
m_BarrelMat.initUnlit();
m_BarrelMat.setColor(CRGBA::White);
m_BarrelMat.setBlend (false);
m_BarrelMat.setAlphaTest (false);
NL3D::CMaterial *barrelMat = m_BarrelMat.getObjectPtr();
barrelMat->setShader(NL3D::CMaterial::Normal);
barrelMat->setBlendFunc(CMaterial::one, CMaterial::zero);
barrelMat->setZWrite(false);
barrelMat->setZFunc(CMaterial::always);
barrelMat->setDoubleSided(true);
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);
m_BarrelQuadLeft.V2 = CVector(0.5f, 1.f, 0.5f);
m_BarrelQuadLeft.V3 = CVector(0.f, 1.f, 0.5f);
m_BarrelQuadRight.V0 = CVector(0.5f, 0.f, 0.5f);
m_BarrelQuadRight.V1 = CVector(1.f, 0.f, 0.5f);
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
m_BarrelQuadLeft.Uv0 = CUV(0.f, 0.f);
m_BarrelQuadLeft.Uv1 = CUV(0.5f, 0.f);
m_BarrelQuadLeft.Uv2 = CUV(0.5f, 1.f);
m_BarrelQuadLeft.Uv3 = CUV(0.f, 1.f);
m_BarrelQuadRight.Uv0 = CUV(0.5f, 0.f);
m_BarrelQuadRight.Uv1 = CUV(1.f, 0.f);
m_BarrelQuadRight.Uv2 = CUV(1.f, 1.f);
m_BarrelQuadRight.Uv3 = CUV(0.5f, 1.f);
}
else
{
nlwarning("VR: No pixel program support");
}
}
bool CStereoOVR::getScreenResolution(uint &width, uint &height)
{
width = m_DevicePtr->HMDInfo.HResolution;
height = m_DevicePtr->HMDInfo.VResolution;
return true;
}
void CStereoOVR::initCamera(uint cid, const NL3D::UCamera *camera)
{
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);
m_RightFrustum[cid] = m_LeftFrustum[cid];
float viewCenter = m_DevicePtr->HMDInfo.HScreenSize * 0.25f;
float eyeProjectionShift = viewCenter - m_DevicePtr->HMDInfo.LensSeparationDistance * 0.5f; // docs say LensSeparationDistance, why not InterpupillaryDistance? related to how the lenses work?
float projectionCenterOffset = (eyeProjectionShift / (m_DevicePtr->HMDInfo.HScreenSize * 0.5f)) * (m_LeftFrustum[cid].Right - m_LeftFrustum[cid].Left); // used logic for this one, but it ends up being the same as the one i made up
nldebug("OVR: projectionCenterOffset = %f", projectionCenterOffset);
m_LeftFrustum[cid].Left -= projectionCenterOffset;
m_LeftFrustum[cid].Right -= projectionCenterOffset;
m_RightFrustum[cid].Left += projectionCenterOffset;
m_RightFrustum[cid].Right += projectionCenterOffset;
// TODO: Clipping frustum should also take into account the IPD
m_ClippingFrustum[cid] = m_LeftFrustum[cid];
m_ClippingFrustum[cid].Left = min(m_LeftFrustum[cid].Left, m_RightFrustum[cid].Left);
m_ClippingFrustum[cid].Right = max(m_LeftFrustum[cid].Right, m_RightFrustum[cid].Right);
}
/// Get the frustum to use for clipping
void CStereoOVR::getClippingFrustum(uint cid, NL3D::UCamera *camera) const
{
camera->setFrustum(m_ClippingFrustum[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()
{
// 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);
if (m_Driver->getPolygonMode() == UDriver::Filled)
{
switch (m_Stage)
{
case 0:
++m_Stage;
m_SubStage = 0;
// stage 1:
// (initBloom)
// clear buffer
// draw scene left
return true;
case 1:
++m_Stage;
m_SubStage = 0;
// stage 2:
// draw scene right
return true;
case 2:
++m_Stage;
m_SubStage = 0;
// stage 3:
// (endBloom)
// draw interface 3d left
return true;
case 3:
++m_Stage;
m_SubStage = 0;
// stage 4:
// draw interface 3d right
return true;
case 4:
++m_Stage;
m_SubStage = 0;
// stage 5:
// (endInterfacesDisplayBloom)
// draw interface 2d left
return true;
case 5:
++m_Stage;
m_SubStage = 0;
// stage 6:
// 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_LeftViewport;
else return m_RightViewport;
}
const NL3D::CFrustum &CStereoOVR::getCurrentFrustum(uint cid) const
{
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]);
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));
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)
{
camera->setPos(mat.getPos());
camera->setRotQuat(mat.getRot());
}
else
{
// camera->setTransformMode(NL3D::UTransformable::DirectMatrix);
camera->setMatrix(mat);
}
}
bool CStereoOVR::wantClear()
{
switch (m_Stage)
{
case 1:
m_SubStage = 1;
return true;
}
return m_Driver->getPolygonMode() != UDriver::Filled;
}
bool CStereoOVR::wantScene()
{
switch (m_Stage)
{
case 1:
case 2:
m_SubStage = 2;
return true;
}
return m_Driver->getPolygonMode() != UDriver::Filled;
}
bool CStereoOVR::wantInterface3D()
{
switch (m_Stage)
{
case 3:
case 4:
m_SubStage = 3;
return true;
}
return m_Driver->getPolygonMode() != UDriver::Filled;
}
bool CStereoOVR::wantInterface2D()
{
switch (m_Stage)
{
case 5:
case 6:
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))
{
static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_BarrelTexU, 0, 0, 0, 0);
return true;
}
return false;
}
/// Returns true if a render target was fully drawn
bool CStereoOVR::endRenderTarget()
{
// after rendering of course
// nlassert(m_SubStage > 1);
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<CDriverUser *>(m_Driver))->setRenderTarget(cu);
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<CDriverUser *>(m_Driver))->getDriver();
NL3D::CMaterial *barrelMat = m_BarrelMat.getObjectPtr();
barrelMat->setTexture(0, m_BarrelTex);
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);
return true;
}
return false;
}
NLMISC::CQuat CStereoOVR::getOrientation() const
{
if (m_OrientationCached)
return m_OrientationCache;
OVR::Quatf quatovr = m_DevicePtr->SensorFusion.GetPredictedOrientation();
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.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;
}
/// Get GUI shift
void CStereoOVR::getInterface2DShift(uint cid, float &x, float &y, float distance) const
{
#if 0
// todo: take into account m_EyePosition
NLMISC::CVector vector = CVector(0.f, -distance, 0.f);
NLMISC::CQuat rot = getOrientation();
rot.invert();
NLMISC::CMatrix mat;
mat.rotate(rot);
//if (m_Stage % 2) mat.translate(CVector(m_DevicePtr->HMDInfo.InterpupillaryDistance * -0.5f, 0.f, 0.f));
//else mat.translate(CVector(m_DevicePtr->HMDInfo.InterpupillaryDistance * 0.5f, 0.f, 0.f));
mat.translate(vector);
CVector proj = CStereoOVR::getCurrentFrustum(cid).project(mat.getPos());
NLMISC::CVector ipd;
if (m_Stage % 2) ipd = CVector(m_DevicePtr->HMDInfo.InterpupillaryDistance * -0.5f, 0.f, 0.f);
else ipd = CVector(m_DevicePtr->HMDInfo.InterpupillaryDistance * 0.5f, 0.f, 0.f);
CVector projipd = CStereoOVR::getCurrentFrustum(cid).project(vector + ipd);
CVector projvec = CStereoOVR::getCurrentFrustum(cid).project(vector);
x = (proj.x + projipd.x - projvec.x - 0.5f);
y = (proj.y + projipd.y - projvec.y - 0.5f);
#elif 1
// Alternative method
// todo: take into account m_EyePosition
NLMISC::CVector vec = CVector(0.f, -distance, 0.f);
NLMISC::CVector ipd;
if (m_Stage % 2) ipd = CVector((m_DevicePtr->HMDInfo.InterpupillaryDistance * m_Scale) * -0.5f, 0.f, 0.f);
else ipd = CVector((m_DevicePtr->HMDInfo.InterpupillaryDistance * m_Scale) * 0.5f, 0.f, 0.f);
NLMISC::CQuat rot = getOrientation();
NLMISC::CQuat modrot = NLMISC::CQuat(CVector(0.f, 1.f, 0.f), NLMISC::Pi);
rot = rot * modrot;
float p = NLMISC::Pi + atan2f(2.0f * ((rot.x * rot.y) + (rot.z * rot.w)), 1.0f - 2.0f * ((rot.y * rot.y) + (rot.w * rot.w)));
if (p > NLMISC::Pi) p -= NLMISC::Pi * 2.0f;
float t = -atan2f(2.0f * ((rot.x * rot.w) + (rot.y * rot.z)), 1.0f - 2.0f * ((rot.z * rot.z) + (rot.w * rot.w)));// // asinf(2.0f * ((rot.x * rot.z) - (rot.w * rot.y)));
CVector rotshift = CVector(p, 0.f, t) * -distance;
CVector proj = CStereoOVR::getCurrentFrustum(cid).project(vec + ipd + rotshift);
x = (proj.x - 0.5f);
y = (proj.y - 0.5f);
#endif
}
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<CStereoDeviceInfo> &devicesOut)
{
s_StereoOVRSystem.Init();
OVR::DeviceEnumerator<OVR::HMDDevice> devices = s_DeviceManager->EnumerateDevices<OVR::HMDDevice>();
uint id = 1;
do
{
CStereoDeviceInfo deviceInfoOut;
OVR::DeviceInfo deviceInfo;
if (devices.IsAvailable())
{
devices.GetDeviceInfo(&deviceInfo);
CStereoOVRDeviceHandle *handle = new CStereoOVRDeviceHandle();
deviceInfoOut.Factory = static_cast<IStereoDeviceFactory *>(handle);
handle->DeviceHandle = devices;
deviceInfoOut.Class = CStereoDeviceInfo::StereoHMD; // 1; // OVR::HMDDevice
deviceInfoOut.Library = CStereoDeviceInfo::OVR; // "Oculus SDK";
deviceInfoOut.Manufacturer = deviceInfo.Manufacturer;
deviceInfoOut.ProductName = deviceInfo.ProductName;
stringstream ser;
ser << id;
deviceInfoOut.Serial = ser.str(); // can't get the real serial from the sdk...
devicesOut.push_back(deviceInfoOut);
++id;
}
} while (devices.Next());
}
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->HMDDevice != NULL;
}
} /* namespace NL3D */
#endif /* HAVE_LIBOVR */
/* end of file */

View file

@ -0,0 +1,249 @@
/************************************************************************************
Filename : stereo_ovf_fp.cpp
Content : Barrel fragment program compiled to a blob of assembly
Created : July 01, 2013
Modified by : Jan Boon (Kaetemi)
Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
************************************************************************************/
namespace NL3D {
const char *g_StereoOVR_fp40 =
"!!ARBfp1.0\n"
"OPTION NV_fragment_program2;\n"
//# cgc version 3.1.0013, build date Apr 18 2012
//# command line args: -profile fp40
//# source file: pp_oculus_vr.cg
//#vendor NVIDIA Corporation
//#version 3.1.0.13
//#profile fp40
//#program pp_oculus_vr
//#semantic pp_oculus_vr.cLensCenter
//#semantic pp_oculus_vr.cScreenCenter
//#semantic pp_oculus_vr.cScale
//#semantic pp_oculus_vr.cScaleIn
//#semantic pp_oculus_vr.cHmdWarpParam
//#semantic pp_oculus_vr.cTex0 : TEX0
//#var float2 texCoord : $vin.TEXCOORD0 : TEX0 : 0 : 1
//#var float2 cLensCenter : : c[0] : 1 : 1
//#var float2 cScreenCenter : : c[1] : 2 : 1
//#var float2 cScale : : c[2] : 3 : 1
//#var float2 cScaleIn : : c[3] : 4 : 1
//#var float4 cHmdWarpParam : : c[4] : 5 : 1
//#var sampler2D nlTex0 : TEX0 : texunit 0 : 6 : 1
//#var float4 oCol : $vout.COLOR : COL : 7 : 1
//#const c[5] = 0.25 0.5 0
"PARAM c[6] = { program.env[0..4],\n" // program.local->program.env!
" { 0.25, 0.5, 0 } };\n"
"TEMP R0;\n"
"TEMP R1;\n"
"SHORT TEMP H0;\n"
"TEMP RC;\n"
"TEMP HC;\n"
"OUTPUT oCol = result.color;\n"
"ADDR R0.xy, fragment.texcoord[0], -c[0];\n"
"MULR R0.xy, R0, c[3];\n"
"MULR R0.z, R0.y, R0.y;\n"
"MADR R1.x, R0, R0, R0.z;\n"
"MULR R0.zw, R1.x, c[4].xywz;\n"
"MADR R1.y, R1.x, c[4], c[4].x;\n"
"MADR R0.w, R0, R1.x, R1.y;\n"
"MULR R0.z, R0, R1.x;\n"
"MADR R0.z, R0, R1.x, R0.w;\n"
"MULR R1.xy, R0, R0.z;\n"
"MOVR R0.xy, c[5];\n"
"ADDR R1.zw, R0.xyxy, c[1].xyxy;\n"
"MOVR R0.zw, c[0].xyxy;\n"
"MADR R0.zw, R1.xyxy, c[2].xyxy, R0;\n"
"MINR R1.xy, R0.zwzw, R1.zwzw;\n"
"ADDR R0.xy, -R0, c[1];\n"
"MAXR R0.xy, R0, R1;\n"
"SEQR H0.xy, R0, R0.zwzw;\n"
"MULXC HC.x, H0, H0.y;\n"
"IF EQ.x;\n"
"MOVR oCol, c[5].z;\n"
"ELSE;\n"
"TEX oCol, R0.zwzw, texture[0], 2D;\n"
"ENDIF;\n"
"END\n";
//# 24 instructions, 2 R-regs, 1 H-regs
const char *g_StereoOVR_arbfp1 =
"!!ARBfp1.0\n"
//# cgc version 3.1.0013, build date Apr 18 2012
//# command line args: -profile arbfp1
//# source file: pp_oculus_vr.cg
//#vendor NVIDIA Corporation
//#version 3.1.0.13
//#profile arbfp1
//#program pp_oculus_vr
//#semantic pp_oculus_vr.cLensCenter
//#semantic pp_oculus_vr.cScreenCenter
//#semantic pp_oculus_vr.cScale
//#semantic pp_oculus_vr.cScaleIn
//#semantic pp_oculus_vr.cHmdWarpParam
//#semantic pp_oculus_vr.cTex0 : TEX0
//#var float2 texCoord : $vin.TEXCOORD0 : TEX0 : 0 : 1
//#var float2 cLensCenter : : c[0] : 1 : 1
//#var float2 cScreenCenter : : c[1] : 2 : 1
//#var float2 cScale : : c[2] : 3 : 1
//#var float2 cScaleIn : : c[3] : 4 : 1
//#var float4 cHmdWarpParam : : c[4] : 5 : 1
//#var sampler2D nlTex0 : TEX0 : texunit 0 : 6 : 1
//#var float4 oCol : $vout.COLOR : COL : 7 : 1
//#const c[5] = 0.25 0.5 0 1
"PARAM c[6] = { program.env[0..4],\n"
" { 0.25, 0.5, 0, 1 } };\n"
"TEMP R0;\n"
"TEMP R1;\n"
"ADD R0.xy, fragment.texcoord[0], -c[0];\n"
"MUL R0.xy, R0, c[3];\n"
"MUL R0.z, R0.y, R0.y;\n"
"MAD R0.z, R0.x, R0.x, R0;\n"
"MUL R0.w, R0.z, c[4];\n"
"MUL R0.w, R0, R0.z;\n"
"MAD R1.y, R0.z, c[4], c[4].x;\n"
"MUL R1.x, R0.z, c[4].z;\n"
"MAD R1.x, R0.z, R1, R1.y;\n"
"MAD R0.z, R0.w, R0, R1.x;\n"
"MUL R0.xy, R0, R0.z;\n"
"MOV R0.zw, c[5].xyxy;\n"
"ADD R1.xy, R0.zwzw, c[1];\n"
"MUL R0.xy, R0, c[2];\n"
"ADD R0.xy, R0, c[0];\n"
"MIN R1.xy, R1, R0;\n"
"ADD R0.zw, -R0, c[1].xyxy;\n"
"MAX R0.zw, R0, R1.xyxy;\n"
"ADD R0.zw, R0, -R0.xyxy;\n"
"ABS R0.zw, R0;\n"
"CMP R0.zw, -R0, c[5].z, c[5].w;\n"
"MUL R0.z, R0, R0.w;\n"
"ABS R0.z, R0;\n"
"CMP R0.z, -R0, c[5], c[5].w;\n"
"ABS R1.x, R0.z;\n"
"TEX R0, R0, texture[0], 2D;\n"
"CMP R1.x, -R1, c[5].z, c[5].w;\n"
"CMP result.color, -R1.x, R0, c[5].z;\n"
"END\n";
//# 28 instructions, 2 R-regs
const char *g_StereoOVR_ps_2_0 =
"ps_2_0\n"
// cgc version 3.1.0013, build date Apr 18 2012
// command line args: -profile ps_2_0
// source file: pp_oculus_vr.cg
//vendor NVIDIA Corporation
//version 3.1.0.13
//profile ps_2_0
//program pp_oculus_vr
//semantic pp_oculus_vr.cLensCenter
//semantic pp_oculus_vr.cScreenCenter
//semantic pp_oculus_vr.cScale
//semantic pp_oculus_vr.cScaleIn
//semantic pp_oculus_vr.cHmdWarpParam
//semantic pp_oculus_vr.cTex0 : TEX0
//var float2 texCoord : $vin.TEXCOORD0 : TEX0 : 0 : 1
//var float2 cLensCenter : : c[0] : 1 : 1
//var float2 cScreenCenter : : c[1] : 2 : 1
//var float2 cScale : : c[2] : 3 : 1
//var float2 cScaleIn : : c[3] : 4 : 1
//var float4 cHmdWarpParam : : c[4] : 5 : 1
//var sampler2D nlTex0 : TEX0 : texunit 0 : 6 : 1
//var float4 oCol : $vout.COLOR : COL : 7 : 1
//const c[5] = -0.25 -0.5 0.25 0.5
//const c[6] = 1 0
"dcl_2d s0\n"
"def c5, -0.25000000, -0.50000000, 0.25000000, 0.50000000\n"
"def c6, 1.00000000, 0.00000000, 0, 0\n"
"dcl t0.xy\n"
"add r0.xy, t0, -c0\n"
"mul r4.xy, r0, c3\n"
"mul r0.x, r4.y, r4.y\n"
"mad r0.x, r4, r4, r0\n"
"mul r1.x, r0, c4.w\n"
"mul r1.x, r1, r0\n"
"mad r3.x, r0, c4.y, c4\n"
"mul r2.x, r0, c4.z\n"
"mad r2.x, r0, r2, r3\n"
"mad r0.x, r1, r0, r2\n"
"mul r0.xy, r4, r0.x\n"
"mul r0.xy, r0, c2\n"
"add r3.xy, r0, c0\n"
"mov r1.x, c5.z\n"
"mov r1.y, c5.w\n"
"mov r2.xy, c1\n"
"add r2.xy, r1, r2\n"
"mov r1.xy, c1\n"
"min r2.xy, r2, r3\n"
"add r1.xy, c5, r1\n"
"max r1.xy, r1, r2\n"
"add r1.xy, r1, -r3\n"
"abs r1.xy, r1\n"
"cmp r1.xy, -r1, c6.x, c6.y\n"
"mul_pp r1.x, r1, r1.y\n"
"abs_pp r1.x, r1\n"
"cmp_pp r1.x, -r1, c6, c6.y\n"
"abs_pp r1.x, r1\n"
"texld r0, r3, s0\n"
"cmp r0, -r1.x, r0, c6.y\n"
"mov oC0, r0\n";
const char *g_StereoOVR_glsl330f =
"#version 330\n"
"\n"
"bool _TMP2;\n"
"bvec2 _TMP1;\n"
"vec2 _TMP3;\n"
"uniform vec2 cLensCenter;\n"
"uniform vec2 cScreenCenter;\n"
"uniform vec2 cScale;\n"
"uniform vec2 cScaleIn;\n"
"uniform vec4 cHmdWarpParam;\n"
"uniform sampler2D nlTex0;\n"
"vec2 _TMP10;\n"
"vec2 _b0011;\n"
"vec2 _a0011;\n"
"in vec4 nlTexCoord0;\n"
"out vec4 nlCol;\n"
"\n"
"void main()\n"
"{\n"
" vec2 _theta;\n"
" float _rSq;\n"
" vec2 _theta1;\n"
" vec2 _tc;\n"
"\n"
" _theta = (nlTexCoord0.xy - cLensCenter)*cScaleIn;\n"
" _rSq = _theta.x*_theta.x + _theta.y*_theta.y;\n"
" _theta1 = _theta*(cHmdWarpParam.x + cHmdWarpParam.y*_rSq + cHmdWarpParam.z*_rSq*_rSq + cHmdWarpParam.w*_rSq*_rSq*_rSq);\n"
" _tc = cLensCenter + cScale*_theta1;\n"
" _a0011 = cScreenCenter - vec2( 0.25, 0.5);\n"
" _b0011 = cScreenCenter + vec2( 0.25, 0.5);\n"
" _TMP3 = min(_b0011, _tc);\n"
" _TMP10 = max(_a0011, _TMP3);\n"
" _TMP1 = bvec2(_TMP10.x == _tc.x, _TMP10.y == _tc.y);\n"
" _TMP2 = _TMP1.x && _TMP1.y;\n"
" if (!_TMP2) {\n"
" nlCol = vec4(0, 0, 0, 0);\n"
" } else {\n"
" nlCol = texture(nlTex0, _tc);\n"
" }\n"
"}\n";
}
/* end of file */

View file

@ -126,9 +126,7 @@ CVegetableManager::~CVegetableManager()
// delete All VP
for(sint i=0; i <NL3D_VEGETABLE_NRDRPASS; i++)
{
delete _VertexProgram[i][0];
delete _VertexProgram[i][1];
_VertexProgram[i][0] = NULL;
_VertexProgram[i][0] = NULL; // smart ptr
_VertexProgram[i][1] = NULL;
}
@ -560,49 +558,159 @@ const char* NL3D_SimpleStartVegetableProgram=
MOV o[COL0].xyz, v[3]; # col.RGBA= vertex color \n\
";
class CVertexProgramVeget : public CVertexProgram
{
public:
struct CIdx
{
// 0-3 modelViewProjection
// 4
// 5
// 6 fog
// 7
uint ProgramConstants0; // 8
uint DirectionalLight; // 9
uint ViewCenter; // 10
uint NegInvTransDist; // 11
// 12
// 13
// 14
// 15
uint AngleAxis; // 16
uint Wind; // 17
uint CosCoeff0; // 18
uint CosCoeff1; // 19
uint CosCoeff2; // 20
uint QuatConstants; // 21
uint PiConstants; // 22
uint LUTSize; // 23 (value = 64)
uint LUT[NL3D_VEGETABLE_VP_LUT_SIZE]; // 32+
};
CVertexProgramVeget(uint vpType, bool fogEnabled)
{
// nelvp
{
CSource *source = new CSource();
source->Profile = nelvp;
source->DisplayName = "nelvp/Veget";
// Init the Vertex Program.
string vpgram;
// start always with Bend.
if( vpType==NL3D_VEGETABLE_RDRPASS_LIGHTED || vpType==NL3D_VEGETABLE_RDRPASS_LIGHTED_2SIDED )
{
source->DisplayName += "/Bend";
vpgram= NL3D_BendProgram;
}
else
{
source->DisplayName += "/FastBend";
vpgram= NL3D_FastBendProgram;
}
// combine the VP according to Type
switch(vpType)
{
case NL3D_VEGETABLE_RDRPASS_LIGHTED:
case NL3D_VEGETABLE_RDRPASS_LIGHTED_2SIDED:
source->DisplayName += "/Lighted";
vpgram+= string(NL3D_LightedStartVegetableProgram);
break;
case NL3D_VEGETABLE_RDRPASS_UNLIT:
case NL3D_VEGETABLE_RDRPASS_UNLIT_2SIDED:
source->DisplayName += "/Unlit";
vpgram+= string(NL3D_UnlitVegetableProgram);
break;
case NL3D_VEGETABLE_RDRPASS_UNLIT_2SIDED_ZSORT:
source->DisplayName += "/UnlitAlphaBlend";
vpgram+= string(NL3D_UnlitAlphaBlendVegetableProgram);
break;
}
// common end of VP
vpgram+= string(NL3D_CommonEndVegetableProgram);
if (fogEnabled)
{
source->DisplayName += "/Fog";
vpgram+= string(NL3D_VegetableProgramFog);
}
vpgram+="\nEND\n";
source->setSource(vpgram);
source->ParamIndices["modelViewProjection"] = 0;
source->ParamIndices["fog"] = 6;
source->ParamIndices["programConstants0"] = 8;
source->ParamIndices["directionalLight"] = 9;
source->ParamIndices["viewCenter"] = 10;
source->ParamIndices["negInvTransDist"] = 11;
source->ParamIndices["angleAxis"] = 16;
source->ParamIndices["wind"] = 17;
source->ParamIndices["cosCoeff0"] = 18;
source->ParamIndices["cosCoeff1"] = 19;
source->ParamIndices["cosCoeff2"] = 20;
source->ParamIndices["quatConstants"] = 21;
source->ParamIndices["piConstants"] = 22;
source->ParamIndices["lutSize"] = 23;
for (uint i = 0; i < NL3D_VEGETABLE_VP_LUT_SIZE; ++i)
{
source->ParamIndices[NLMISC::toString("lut[%i]", i)] = 32 + i;
}
addSource(source);
}
// TODO_VP_GLSL
}
virtual ~CVertexProgramVeget()
{
}
virtual void buildInfo()
{
m_Idx.ProgramConstants0 = getUniformIndex("programConstants0");
nlassert(m_Idx.ProgramConstants0 != ~0);
m_Idx.DirectionalLight = getUniformIndex("directionalLight");
nlassert(m_Idx.DirectionalLight != ~0);
m_Idx.ViewCenter = getUniformIndex("viewCenter");
nlassert(m_Idx.ViewCenter != ~0);
m_Idx.NegInvTransDist = getUniformIndex("negInvTransDist");
nlassert(m_Idx.NegInvTransDist != ~0);
m_Idx.AngleAxis = getUniformIndex("angleAxis");
nlassert(m_Idx.AngleAxis != ~0);
m_Idx.Wind = getUniformIndex("wind");
nlassert(m_Idx.Wind != ~0);
m_Idx.CosCoeff0 = getUniformIndex("cosCoeff0");
nlassert(m_Idx.CosCoeff0 != ~0);
m_Idx.CosCoeff1 = getUniformIndex("cosCoeff1");
nlassert(m_Idx.CosCoeff1 != ~0);
m_Idx.CosCoeff2 = getUniformIndex("cosCoeff2");
nlassert(m_Idx.CosCoeff2 != ~0);
m_Idx.QuatConstants = getUniformIndex("quatConstants");
nlassert(m_Idx.QuatConstants != ~0);
m_Idx.PiConstants = getUniformIndex("piConstants");
nlassert(m_Idx.PiConstants != ~0);
m_Idx.LUTSize = getUniformIndex("lutSize");
nlassert(m_Idx.LUTSize != ~0);
for (uint i = 0; i < NL3D_VEGETABLE_VP_LUT_SIZE; ++i)
{
m_Idx.LUT[i] = getUniformIndex(NLMISC::toString("lut[%i]", i));
nlassert(m_Idx.LUT[i] != ~0);
}
}
const CIdx &idx() const { return m_Idx; }
private:
CIdx m_Idx;
};
// ***************************************************************************
void CVegetableManager::initVertexProgram(uint vpType, bool fogEnabled)
{
nlassert(_LastDriver); // update driver should have been called at least once !
// Init the Vertex Program.
string vpgram;
// start always with Bend.
if( vpType==NL3D_VEGETABLE_RDRPASS_LIGHTED || vpType==NL3D_VEGETABLE_RDRPASS_LIGHTED_2SIDED )
vpgram= NL3D_BendProgram;
else
vpgram= NL3D_FastBendProgram;
// combine the VP according to Type
switch(vpType)
{
case NL3D_VEGETABLE_RDRPASS_LIGHTED:
case NL3D_VEGETABLE_RDRPASS_LIGHTED_2SIDED:
vpgram+= string(NL3D_LightedStartVegetableProgram);
break;
case NL3D_VEGETABLE_RDRPASS_UNLIT:
case NL3D_VEGETABLE_RDRPASS_UNLIT_2SIDED:
vpgram+= string(NL3D_UnlitVegetableProgram);
break;
case NL3D_VEGETABLE_RDRPASS_UNLIT_2SIDED_ZSORT:
vpgram+= string(NL3D_UnlitAlphaBlendVegetableProgram);
break;
}
// common end of VP
vpgram+= string(NL3D_CommonEndVegetableProgram);
if (fogEnabled)
{
vpgram+= string(NL3D_VegetableProgramFog);
}
vpgram+="\nEND\n";
// create VP.
_VertexProgram[vpType][fogEnabled ? 1 : 0] = new CVertexProgram(vpgram.c_str());
_VertexProgram[vpType][fogEnabled ? 1 : 0] = new CVertexProgramVeget(vpType, fogEnabled);
}
@ -1756,42 +1864,48 @@ public:
// ***************************************************************************
void CVegetableManager::setupVertexProgramConstants(IDriver *driver)
void CVegetableManager::setupVertexProgramConstants(IDriver *driver, bool fogEnabled)
{
nlassert(_ActiveVertexProgram);
// Standard
// setup VertexProgram constants.
// c[0..3] take the ModelViewProjection Matrix. After setupModelMatrix();
driver->setConstantMatrix(0, IDriver::ModelViewProjection, IDriver::Identity);
driver->setUniformMatrix(IDriver::VertexProgram, _ActiveVertexProgram->getUniformIndex(CProgramIndex::ModelViewProjection), IDriver::ModelViewProjection, IDriver::Identity);
// c[6] take the Fog vector. After setupModelMatrix();
driver->setConstantFog(6);
if (fogEnabled)
{
driver->setUniformFog(IDriver::VertexProgram, _ActiveVertexProgram->getUniformIndex(CProgramIndex::Fog));
}
// c[8] take useful constants.
driver->setConstant(8, 0, 1, 0.5f, 2);
driver->setUniform4f(IDriver::VertexProgram, _ActiveVertexProgram->idx().ProgramConstants0, 0, 1, 0.5f, 2);
// c[9] take normalized directional light
driver->setConstant(9, _DirectionalLight);
driver->setUniform3f(IDriver::VertexProgram, _ActiveVertexProgram->idx().DirectionalLight, _DirectionalLight);
// c[10] take pos of camera
driver->setConstant(10, _ViewCenter);
driver->setUniform3f(IDriver::VertexProgram, _ActiveVertexProgram->idx().ViewCenter, _ViewCenter);
// c[11] take factor for Blend formula
driver->setConstant(11, -1.f/NL3D_VEGETABLE_BLOCK_BLEND_TRANSITION_DIST, 0, 0, 0);
driver->setUniform1f(IDriver::VertexProgram, _ActiveVertexProgram->idx().NegInvTransDist, -1.f/NL3D_VEGETABLE_BLOCK_BLEND_TRANSITION_DIST);
// Bend.
// c[16]= quaternion axis. w==1, and z must be 0
driver->setConstant( 16, _AngleAxis.x, _AngleAxis.y, _AngleAxis.z, 1);
driver->setUniform4f(IDriver::VertexProgram, _ActiveVertexProgram->idx().AngleAxis, _AngleAxis, 1);
// c[17]= {timeAnim, WindPower, WindPower*(1-WindBendMin)/2, 0)}
driver->setConstant( 17, (float)_WindAnimTime, _WindPower, _WindPower*(1-_WindBendMin)/2, 0 );
driver->setUniform3f(IDriver::VertexProgram, _ActiveVertexProgram->idx().Wind, (float)_WindAnimTime, _WindPower, _WindPower * (1 - _WindBendMin) / 2);
// c[18]= High order Taylor cos coefficient: { -1/2, 1/24, -1/720, 1/40320 }
driver->setConstant( 18, -1/2.f, 1/24.f, -1/720.f, 1/40320.f );
driver->setUniform4f(IDriver::VertexProgram, _ActiveVertexProgram->idx().CosCoeff0, -1/2.f, 1/24.f, -1/720.f, 1/40320.f );
// c[19]= Low order Taylor cos coefficient: { 1, -1/2, 1/24, -1/720 }
driver->setConstant( 19, 1, -1/2.f, 1/24.f, -1/720.f );
driver->setUniform4f(IDriver::VertexProgram, _ActiveVertexProgram->idx().CosCoeff1, 1, -1/2.f, 1/24.f, -1/720.f );
// c[20]= Low order Taylor sin coefficient: { 1, -1/6, 1/120, -1/5040 }
driver->setConstant( 20, 1, -1/6.f, 1/120.f, -1/5040.f );
driver->setUniform4f(IDriver::VertexProgram, _ActiveVertexProgram->idx().CosCoeff2, 1, -1/6.f, 1/120.f, -1/5040.f );
// c[21]= Special constant vector for quatToMatrix: { 0, 1, -1, 0 }
driver->setConstant( 21, 0.f, 1.f, -1.f, 0.f);
driver->setUniform4f(IDriver::VertexProgram, _ActiveVertexProgram->idx().QuatConstants, 0.f, 1.f, -1.f, 0.f);
// c[22]= {0.5f, Pi, 2*Pi, 1/(2*Pi)}
driver->setConstant( 22, 0.5f, (float)Pi, (float)(2*Pi), (float)(1/(2*Pi)) );
driver->setUniform4f(IDriver::VertexProgram, _ActiveVertexProgram->idx().PiConstants, 0.5f, (float)Pi, (float)(2*Pi), (float)(1/(2*Pi)));
// c[23]= {NL3D_VEGETABLE_VP_LUT_SIZE, 0, 0, 0}. NL3D_VEGETABLE_VP_LUT_SIZE==64.
driver->setConstant( 23, NL3D_VEGETABLE_VP_LUT_SIZE, 0.f, 0.f, 0.f );
driver->setUniform1f(IDriver::VertexProgram, _ActiveVertexProgram->idx().LUTSize, NL3D_VEGETABLE_VP_LUT_SIZE);
// Fill constant. Start at 32.
@ -1799,7 +1913,7 @@ void CVegetableManager::setupVertexProgramConstants(IDriver *driver)
{
CVector2f cur= _WindTable[i];
CVector2f delta= _WindDeltaTable[i];
driver->setConstant( 32+i, cur.x, cur.y, delta.x, delta.y );
driver->setUniform4f(IDriver::VertexProgram, _ActiveVertexProgram->idx().LUT[i], cur.x, cur.y, delta.x, delta.y);
}
}
@ -1925,10 +2039,6 @@ void CVegetableManager::render(const CVector &viewCenter, const CVector &front
}
// setup VP constants.
setupVertexProgramConstants(driver);
// Setup TexEnvs for Dynamic lightmapping
//--------------------
// if the dynamic lightmap is provided
@ -1968,6 +2078,12 @@ void CVegetableManager::render(const CVector &viewCenter, const CVector &front
_VegetableMaterial.setZWrite(true);
_VegetableMaterial.setAlphaTestThreshold(0.5f);
bool uprogst = driver->isUniformProgramState();
bool progstateset[NL3D_VEGETABLE_NRDRPASS];
for (sint rdrPass = 0; rdrPass < NL3D_VEGETABLE_NRDRPASS; ++rdrPass)
{
progstateset[rdrPass] = false;
}
/*
Prefer sort with Soft / Hard first.
@ -1995,14 +2111,20 @@ void CVegetableManager::render(const CVector &viewCenter, const CVector &front
// set the 2Sided flag in the material
_VegetableMaterial.setDoubleSided( doubleSided );
// Activate the unique material.
driver->setupMaterial(_VegetableMaterial);
// activate Vertex program first.
//nlinfo("\nSTARTVP\n%s\nENDVP\n", _VertexProgram[rdrPass]->getProgram().c_str());
nlverify(driver->activeVertexProgram(_VertexProgram[rdrPass][fogged ? 1 : 0]));
_ActiveVertexProgram = _VertexProgram[rdrPass][fogged ? 1 : 0];
nlverify(driver->activeVertexProgram(_ActiveVertexProgram));
// Set VP constants
if (!progstateset[uprogst ? rdrPass : 0])
{
setupVertexProgramConstants(driver, uprogst ? fogged : true);
}
// Activate the unique material.
driver->setupMaterial(_VegetableMaterial);
// Activate the good VBuffer
vbAllocator.activate();
@ -2222,6 +2344,7 @@ void CVegetableManager::render(const CVector &viewCenter, const CVector &front
// disable VertexProgram.
driver->activeVertexProgram(NULL);
_ActiveVertexProgram = NULL;
// restore Fog.
@ -2261,25 +2384,25 @@ void CVegetableManager::setupRenderStateForBlendLayerModel(IDriver *driver)
// set model matrix to the manager matrix.
driver->setupModelMatrix(_ManagerMatrix);
// setup VP constants.
setupVertexProgramConstants(driver);
// Setup RdrPass.
//=============
uint rdrPass= NL3D_VEGETABLE_RDRPASS_UNLIT_2SIDED_ZSORT;
// Activate the unique material (correclty setuped for AlphaBlend in render()).
driver->setupMaterial(_VegetableMaterial);
// activate Vertex program first.
//nlinfo("\nSTARTVP\n%s\nENDVP\n", _VertexProgram[rdrPass]->getProgram().c_str());
nlverify(driver->activeVertexProgram(_VertexProgram[rdrPass][fogged ? 1 : 0]));
_ActiveVertexProgram = _VertexProgram[rdrPass][fogged ? 1 : 0];
nlverify(driver->activeVertexProgram(_ActiveVertexProgram));
if (fogged)
// setup VP constants.
setupVertexProgramConstants(driver, fogged);
/*if (fogged) // duplicate
{
driver->setConstantFog(6);
}
driver->setCon/stantFog(6);
}*/
// Activate the unique material (correclty setuped for AlphaBlend in render()).
driver->setupMaterial(_VegetableMaterial);
}
@ -2302,6 +2425,7 @@ void CVegetableManager::exitRenderStateForBlendLayerModel(IDriver *driver)
{
// disable VertexProgram.
driver->activeVertexProgram(NULL);
_ActiveVertexProgram = NULL;
// restore Fog.
driver->enableFog(_BkupFog);

View file

@ -98,7 +98,7 @@ void CVegetableVBAllocator::updateDriver(IDriver *driver)
_VBHardOk= false;
// Driver must support VP.
nlassert(_Driver->isVertexProgramSupported());
nlassert(_Driver->supportVertexProgram());
// must reallocate the VertexBuffer.
if( _NumVerticesAllocated>0 )

View file

@ -24,34 +24,28 @@
namespace NL3D
{
// ***************************************************************************
IVertexProgramDrvInfos::IVertexProgramDrvInfos (IDriver *drv, ItVtxPrgDrvInfoPtrList it)
CVertexProgram::CVertexProgram()
{
_Driver= drv;
_DriverIterator= it;
}
// ***************************************************************************
IVertexProgramDrvInfos::~IVertexProgramDrvInfos ()
CVertexProgram::CVertexProgram(const char *nelvp)
{
_Driver->removeVtxPrgDrvInfoPtr (_DriverIterator);
CSource *source = new CSource();
source->Profile = IProgram::nelvp;
source->setSource(nelvp);
addSource(source);
}
// ***************************************************************************
CVertexProgram::CVertexProgram (const char* program)
{
_Program=program;
}
// ***************************************************************************
CVertexProgram::~CVertexProgram ()
{
// Must kill the drv mirror of this VB.
_DrvInfo.kill();
}
} // NL3D

View file

@ -227,8 +227,7 @@ void CWaterEnvMap::doInit()
}
}
static CVertexProgram testMeshVP(
static const char *testMeshVPstr =
"!!VP1.0\n\
DP4 o[HPOS].x, c[0], v[0]; \n\
DP4 o[HPOS].y, c[1], v[0]; \n\
@ -236,14 +235,57 @@ static CVertexProgram testMeshVP(
DP4 o[HPOS].w, c[3], v[0]; \n\
MAD o[COL0], v[8], c[4].xxxx, c[4].yyyy; \n\
MOV o[TEX0], v[8]; \n\
END"
);
END";
class CVertexProgramTestMeshVP : public CVertexProgram
{
public:
struct CIdx
{
uint ProgramConstant0;
};
CVertexProgramTestMeshVP()
{
// nelvp
{
CSource *source = new CSource();
source->Profile = nelvp;
source->DisplayName = "testMeshVP/nelvp";
source->setSourcePtr(testMeshVPstr);
source->ParamIndices["modelViewProjection"] = 0;
source->ParamIndices["programConstant0"] = 4;
addSource(source);
}
// TODO_VP_GLSL
}
virtual ~CVertexProgramTestMeshVP()
{
}
virtual void buildInfo()
{
m_Idx.ProgramConstant0 = getUniformIndex("programConstant0");
nlassert(m_Idx.ProgramConstant0 != ~0);
}
inline const CIdx &idx() { return m_Idx; }
private:
CIdx m_Idx;
};
static NLMISC::CSmartPtr<CVertexProgramTestMeshVP> testMeshVP;
// *******************************************************************************
void CWaterEnvMap::renderTestMesh(IDriver &driver)
{
if (!testMeshVP)
{
testMeshVP = new CVertexProgramTestMeshVP();
}
doInit();
CMaterial testMat;
testMat.setLighting(false);
@ -257,13 +299,12 @@ void CWaterEnvMap::renderTestMesh(IDriver &driver)
testMat.setZWrite(false);
testMat.setZFunc(CMaterial::always);
// tmp : test cubemap
driver.activeVertexProgram(&testMeshVP);
driver.activeVertexProgram(testMeshVP);
driver.activeVertexBuffer(_TestVB);
driver.activeIndexBuffer(_TestIB);
driver.setConstantMatrix(0, IDriver::ModelViewProjection, IDriver::Identity); // tmp
_MaterialPassThruZTest.setTexture(0, _EnvCubic);
driver.setConstantMatrix(0, IDriver::ModelViewProjection, IDriver::Identity);
driver.setConstant(4, 2.f, 1.f, 0.f, 0.f);
driver.setUniformMatrix(IDriver::VertexProgram, testMeshVP->getUniformIndex(CProgramIndex::ModelViewProjection), IDriver::ModelViewProjection, IDriver::Identity);
driver.setUniform2f(IDriver::VertexProgram, testMeshVP->idx().ProgramConstant0, 2.f, 1.f);
//driver.renderTriangles(testMat, 0, TEST_VB_NUM_TRIS);
driver.renderTriangles(_MaterialPassThruZTest, 0, TEST_VB_NUM_TRIS);
driver.activeVertexProgram(NULL);

View file

@ -61,7 +61,7 @@ void CWaterModel::setupVertexBuffer(CVertexBuffer &vb, uint numWantedVertices, I
vb.setNumVertices(0);
vb.setName("Water");
vb.setPreferredMemory(CVertexBuffer::AGPPreferred, false);
if (drv->isWaterShaderSupported())
if (drv->supportWaterShader())
{
vb.setVertexFormat(CVertexBuffer::PositionFlag);
}
@ -377,7 +377,7 @@ void CWaterModel::traverseRender()
#ifndef FORCE_SIMPLE_WATER_RENDER
if (!drv->isWaterShaderSupported())
if (!drv->supportWaterShader())
#endif
{
doSimpleRender(drv);
@ -903,11 +903,12 @@ void CWaterModel::setupMaterialNVertexShader(IDriver *drv, CWaterShape *shape, c
_WaterMat.setZWrite(true);
_WaterMat.setShader(CMaterial::Water);
}
const uint cstOffset = 5; // 4 places for the matrix
NLMISC::CVectorH cst[13];
//=========================//
// setup Water material //
//=========================//
shape->initVertexProgram();
CVertexProgramWaterVPNoWave *program = shape->_ColorMap ? CWaterShape::_VertexProgramNoWaveDiffuse : CWaterShape::_VertexProgramNoWave;
drv->activeVertexProgram(program);
CWaterModel::_WaterMat.setTexture(0, shape->_BumpMap[0]);
CWaterModel::_WaterMat.setTexture(1, shape->_BumpMap[1]);
CWaterModel::_WaterMat.setTexture(3, shape->_ColorMap);
@ -953,25 +954,21 @@ void CWaterModel::setupMaterialNVertexShader(IDriver *drv, CWaterShape *shape, c
{
// setup 2x3 matrix for lookup in diffuse map
updateDiffuseMapMatrix();
cst[11].set(_ColorMapMatColumn0.x, _ColorMapMatColumn1.x, 0, _ColorMapMatColumn0.x * obsPos.x + _ColorMapMatColumn1.x * obsPos.y + _ColorMapMatPos.x);
cst[12].set(_ColorMapMatColumn0.y, _ColorMapMatColumn1.y, 0, _ColorMapMatColumn0.y * obsPos.x + _ColorMapMatColumn1.y * obsPos.y + _ColorMapMatPos.y);
drv->setUniform4f(IDriver::VertexProgram, program->idx().DiffuseMapVector0, _ColorMapMatColumn0.x, _ColorMapMatColumn1.x, 0, _ColorMapMatColumn0.x * obsPos.x + _ColorMapMatColumn1.x * obsPos.y + _ColorMapMatPos.x);
drv->setUniform4f(IDriver::VertexProgram, program->idx().DiffuseMapVector1, _ColorMapMatColumn0.y, _ColorMapMatColumn1.y, 0, _ColorMapMatColumn0.y * obsPos.x + _ColorMapMatColumn1.y * obsPos.y + _ColorMapMatPos.y);
}
/// set matrix
drv->setConstantMatrix(0, IDriver::ModelViewProjection, IDriver::Identity);
// set builtins
drv->setUniformMatrix(IDriver::VertexProgram, program->getUniformIndex(CProgramIndex::ModelViewProjection), IDriver::ModelViewProjection, IDriver::Identity);
drv->setUniformFog(IDriver::VertexProgram, program->getUniformIndex(CProgramIndex::Fog));
// retrieve current time
double date = scene->getCurrentTime();
// set bumpmaps pos
cst[6].set(fmodf(obsPos.x * shape->_HeightMapScale[0].x, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[0].x, 1), fmodf(shape->_HeightMapScale[0].y * obsPos.y, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[0].y, 1), 0.f, 1.f); // bump map 0 offset
cst[5].set(shape->_HeightMapScale[0].x, shape->_HeightMapScale[0].y, 0, 0); // bump map 0 scale
cst[8].set(fmodf(shape->_HeightMapScale[1].x * obsPos.x, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[1].x, 1), fmodf(shape->_HeightMapScale[1].y * obsPos.y, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[1].y, 1), 0.f, 1.f); // bump map 1 offset
cst[7].set(shape->_HeightMapScale[1].x, shape->_HeightMapScale[1].y, 0, 0); // bump map 1 scale
cst[9].set(0, 0, obsPos.z - zHeight, 1.f);
cst[10].set(0.5f, 0.5f, 0.f, 1.f); // used to scale reflected ray into the envmap
/// set all our constants in one call
drv->setConstant(cstOffset, sizeof(cst) / sizeof(cst[0]) - cstOffset, (float *) &cst[cstOffset]);
shape->initVertexProgram();
drv->activeVertexProgram(shape->_ColorMap ? CWaterShape::_VertexProgramNoWaveDiffuse.get() : CWaterShape::_VertexProgramNoWave.get());
drv->setConstantFog(4);
drv->setUniform4f(IDriver::VertexProgram, program->idx().BumpMap0Offset, fmodf(obsPos.x * shape->_HeightMapScale[0].x, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[0].x, 1), fmodf(shape->_HeightMapScale[0].y * obsPos.y, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[0].y, 1), 0.f, 1.f); // bump map 0 offset
drv->setUniform4f(IDriver::VertexProgram, program->idx().BumpMap0Scale, shape->_HeightMapScale[0].x, shape->_HeightMapScale[0].y, 0, 0); // bump map 0 scale
drv->setUniform4f(IDriver::VertexProgram, program->idx().BumpMap1Offset, fmodf(shape->_HeightMapScale[1].x * obsPos.x, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[1].x, 1), fmodf(shape->_HeightMapScale[1].y * obsPos.y, 1.f) + (float) fmod(date * shape->_HeightMapSpeed[1].y, 1), 0.f, 1.f); // bump map 1 offset
drv->setUniform4f(IDriver::VertexProgram, program->idx().BumpMap1Scale, shape->_HeightMapScale[1].x, shape->_HeightMapScale[1].y, 0, 0); // bump map 1 scale
drv->setUniform4f(IDriver::VertexProgram, program->idx().ObserverHeight, 0, 0, obsPos.z - zHeight, 1.f);
drv->setUniform4f(IDriver::VertexProgram, program->idx().ScaleReflectedRay, 0.5f, 0.5f, 0.f, 1.f); // used to scale reflected ray into the envmap
}
//================================================
@ -1363,7 +1360,7 @@ uint CWaterModel::getNumWantedVertices()
uint CWaterModel::fillVB(void *datas, uint startTri, IDriver &drv)
{
H_AUTO( NL3D_Water_Render );
if (drv.isWaterShaderSupported())
if (drv.supportWaterShader())
{
return fillVBHard(datas, startTri);
}
@ -1657,7 +1654,7 @@ void CWaterModel::traverseRender()
drv->setupModelMatrix(modelMat);
bool isAbove = obsPos.z > getWorldMatrix().getPos().z;
CVertexBuffer &vb = renderTrav.Scene->getWaterVB();
if (drv->isWaterShaderSupported())
if (drv->supportWaterShader())
{
setupMaterialNVertexShader(drv, shape, obsPos, isAbove, zHeight);
nlassert(vb.getNumVertices() > 0);

View file

@ -81,7 +81,69 @@ DP4 o[TEX3].x, v[0], c[11]; #compute uv for diffuse texture \n\
DP4 o[TEX3].y, v[0], c[12]; \n\
END";
CVertexProgramWaterVPNoWave::CVertexProgramWaterVPNoWave(bool diffuse)
{
m_Diffuse = diffuse;
// nelvp
{
CSource *source = new CSource();
source->Profile = nelvp;
source->DisplayName = "WaterVPNoWave/nelvp";
source->ParamIndices["modelViewProjection"] = 0;
source->ParamIndices["fog"] = 4;
source->ParamIndices["bumpMap0Scale"] = 5;
source->ParamIndices["bumpMap0Offset"] = 6;
source->ParamIndices["bumpMap1Scale"] = 7;
source->ParamIndices["bumpMap1Offset"] = 8;
source->ParamIndices["observerHeight"] = 9;
source->ParamIndices["scaleReflectedRay"] = 10;
if (diffuse)
{
source->DisplayName += "/diffuse";
source->ParamIndices["diffuseMapVector0"] = 11;
source->ParamIndices["diffuseMapVector1"] = 12;
source->setSourcePtr(WaterVPNoWaveDiffuse);
}
else
{
source->setSourcePtr(WaterVPNoWave);
}
addSource(source);
}
// glsl330v
{
// TODO_VP_GLSL
// CSource *source = new CSource();
// source->Profile = glsl330v;
// source->DisplayName = "WaterVPNoWave/glsl330v";
// if (diffuse) source->DisplayName += "/diffuse";
// source->setSource...
// addSource(source);
}
}
void CVertexProgramWaterVPNoWave::buildInfo()
{
m_Idx.BumpMap0Scale = getUniformIndex("bumpMap0Scale");
nlassert(m_Idx.BumpMap0Scale != ~0);
m_Idx.BumpMap0Offset = getUniformIndex("bumpMap0Offset");
nlassert(m_Idx.BumpMap0Offset != ~0);
m_Idx.BumpMap1Scale = getUniformIndex("bumpMap1Scale");
nlassert(m_Idx.BumpMap1Scale != ~0);
m_Idx.BumpMap1Offset = getUniformIndex("bumpMap1Offset");
nlassert(m_Idx.BumpMap1Offset != ~0);
m_Idx.ObserverHeight = getUniformIndex("observerHeight");
nlassert(m_Idx.ObserverHeight != ~0);
m_Idx.ScaleReflectedRay = getUniformIndex("scaleReflectedRay");
nlassert(m_Idx.ScaleReflectedRay != ~0);
if (m_Diffuse)
{
m_Idx.DiffuseMapVector0 = getUniformIndex("diffuseMapVector0");
nlassert(m_Idx.DiffuseMapVector0 != ~0);
m_Idx.DiffuseMapVector1 = getUniformIndex("diffuseMapVector1");
nlassert(m_Idx.DiffuseMapVector1 != ~0);
}
}
////////////////
// WAVY WATER //
@ -188,15 +250,15 @@ uint32 CWaterShape::_XGridBorder = 4;
uint32 CWaterShape::_YGridBorder = 4;
uint32 CWaterShape::_MaxGridSize;
bool CWaterShape::_GridSizeTouched = true;
std::auto_ptr<CVertexProgram> CWaterShape::_VertexProgramBump1;
std::auto_ptr<CVertexProgram> CWaterShape::_VertexProgramBump2;
std::auto_ptr<CVertexProgram> CWaterShape::_VertexProgramBump1Diffuse;
std::auto_ptr<CVertexProgram> CWaterShape::_VertexProgramBump2Diffuse;
std::auto_ptr<CVertexProgram> CWaterShape::_VertexProgramNoBump;
std::auto_ptr<CVertexProgram> CWaterShape::_VertexProgramNoBumpDiffuse;
NLMISC::CSmartPtr<CVertexProgram> CWaterShape::_VertexProgramBump1;
NLMISC::CSmartPtr<CVertexProgram> CWaterShape::_VertexProgramBump2;
NLMISC::CSmartPtr<CVertexProgram> CWaterShape::_VertexProgramBump1Diffuse;
NLMISC::CSmartPtr<CVertexProgram> CWaterShape::_VertexProgramBump2Diffuse;
NLMISC::CSmartPtr<CVertexProgram> CWaterShape::_VertexProgramNoBump;
NLMISC::CSmartPtr<CVertexProgram> CWaterShape::_VertexProgramNoBumpDiffuse;
// water with no waves
std::auto_ptr<CVertexProgram> CWaterShape::_VertexProgramNoWave;
std::auto_ptr<CVertexProgram> CWaterShape::_VertexProgramNoWaveDiffuse;
NLMISC::CSmartPtr<CVertexProgramWaterVPNoWave> CWaterShape::_VertexProgramNoWave;
NLMISC::CSmartPtr<CVertexProgramWaterVPNoWave> CWaterShape::_VertexProgramNoWaveDiffuse;
/** Build a vertex program for water depending on requirements
@ -223,6 +285,7 @@ static CVertexProgram *BuildWaterVP(bool diffuseMap, bool bumpMap, bool use2Bump
vp += "\nEND";
return new CVertexProgram(vp.c_str());
// TODO_VP_GLSL
}
@ -321,17 +384,17 @@ void CWaterShape::initVertexProgram()
if (!created)
{
// waves
_VertexProgramBump1 = std::auto_ptr<CVertexProgram>(BuildWaterVP(false, true, false));
_VertexProgramBump2 = std::auto_ptr<CVertexProgram>(BuildWaterVP(false, true, true));
_VertexProgramBump1 = BuildWaterVP(false, true, false);
_VertexProgramBump2 = BuildWaterVP(false, true, true);
_VertexProgramBump1Diffuse = std::auto_ptr<CVertexProgram>(BuildWaterVP(true, true, false));
_VertexProgramBump2Diffuse = std::auto_ptr<CVertexProgram>(BuildWaterVP(true, true, true));
_VertexProgramBump1Diffuse = BuildWaterVP(true, true, false);
_VertexProgramBump2Diffuse = BuildWaterVP(true, true, true);
_VertexProgramNoBump = std::auto_ptr<CVertexProgram>(BuildWaterVP(false, false, false));
_VertexProgramNoBumpDiffuse = std::auto_ptr<CVertexProgram>(BuildWaterVP(true, false, false));
_VertexProgramNoBump = BuildWaterVP(false, false, false);
_VertexProgramNoBumpDiffuse = BuildWaterVP(true, false, false);
// no waves
_VertexProgramNoWave.reset(new CVertexProgram(WaterVPNoWave));
_VertexProgramNoWaveDiffuse.reset(new CVertexProgram(WaterVPNoWaveDiffuse));
_VertexProgramNoWave = new CVertexProgramWaterVPNoWave(false);
_VertexProgramNoWaveDiffuse = new CVertexProgramWaterVPNoWave(true); // TODO_VP_GLSL
created = true;
}
}
@ -372,7 +435,7 @@ void CWaterShape::flushTextures (IDriver &driver, uint selectedTexture)
/*
if (
(driver.supportTextureShaders() && driver.isTextureAddrModeSupported(CMaterial::OffsetTexture))
(driver.supportTextureShaders() && driver.supportTextureAddrMode(CMaterial::OffsetTexture))
|| driver.supportEMBM()
)
{

View file

@ -0,0 +1,85 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
#include <nel/misc/types_nl.h>
#include "camera.h"
#include <nel/3d/stereo_display.h>
#include "global.h"
#include "misc.h"
using namespace NLMISC;
using namespace NL3D;
//---------------------------------------------------
// update the camera perspective setup
//---------------------------------------------------
void updateCameraPerspective()
{
float fov, aspectRatio;
computeCurrentFovAspectRatio(fov, aspectRatio);
// change the perspective of the scene
if(!MainCam.empty())
MainCam.setPerspective(fov, aspectRatio, CameraSetupZNear, ClientCfg.Vision);
// change the perspective of the root scene
if(SceneRoot)
{
UCamera cam= SceneRoot->getCam();
cam.setPerspective(fov, aspectRatio, SceneRootCameraZNear, SceneRootCameraZFar);
}
}
void buildCameraClippingPyramid(std::vector<CPlane> &planes)
{
if (StereoDisplay) StereoDisplay->getClippingFrustum(0, &MainCam);
// Compute pyramid in view basis.
CVector pfoc(0,0,0);
const CFrustum &frustum = MainCam.getFrustum();
InvMainSceneViewMatrix = MainCam.getMatrix();
MainSceneViewMatrix = InvMainSceneViewMatrix;
MainSceneViewMatrix.invert();
CVector lb(frustum.Left, frustum.Near, frustum.Bottom );
CVector lt(frustum.Left, frustum.Near, frustum.Top );
CVector rb(frustum.Right, frustum.Near, frustum.Bottom );
CVector rt(frustum.Right, frustum.Near, frustum.Top );
CVector lbFar(frustum.Left, ClientCfg.CharacterFarClip, frustum.Bottom);
CVector ltFar(frustum.Left, ClientCfg.CharacterFarClip, frustum.Top );
CVector rtFar(frustum.Right, ClientCfg.CharacterFarClip, frustum.Top );
planes.resize (4);
// planes[0].make(lbFar, ltFar, rtFar);
planes[0].make(pfoc, lt, lb);
planes[1].make(pfoc, rt, lt);
planes[2].make(pfoc, rb, rt);
planes[3].make(pfoc, lb, rb);
// Compute pyramid in World basis.
// The vector transformation M of a plane p is computed as p*M-1.
// Here, ViewMatrix== CamMatrix-1. Hence the following formula.
uint i;
for (i = 0; i < 4; i++)
{
planes[i] = planes[i]*MainSceneViewMatrix;
}
}
/* end of file */

View file

@ -0,0 +1,29 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
#ifndef CL_CAMERA_H
#define CL_CAMERA_H
#include <nel/misc/types_nl.h>
#include <nel/misc/plane.h>
void updateCameraPerspective();
void buildCameraClippingPyramid(std::vector<NLMISC::CPlane> &planes);
#endif // CL_CAMERA_H
/* end of file */

View file

@ -302,6 +302,10 @@ CClientConfig::CClientConfig()
Contrast = 0.f; // Default Monitor Contrast.
Luminosity = 0.f; // Default Monitor Luminosity.
Gamma = 0.f; // Default Monitor Gamma.
VREnable = false;
VRDisplayDevice = "Auto";
VRDisplayDeviceId = "";
Local = false; // Default is Net Mode.
FSHost = ""; // Default Host.
@ -847,6 +851,9 @@ void CClientConfig::setValues()
else
cfgWarning ("Default value used for 'Driver3D' !!!");
READ_BOOL_FV(VREnable)
READ_STRING_FV(VRDisplayDevice)
READ_STRING_FV(VRDisplayDeviceId)
////////////
// INPUTS //

View file

@ -146,6 +146,11 @@ struct CClientConfig
/// Monitor Gamma [-1 ~ 1], default 0
float Gamma;
// VR
bool VREnable;
std::string VRDisplayDevice;
std::string VRDisplayDeviceId;
/// Client in Local mode or not.
bool Local;
/// Host.

View file

@ -84,7 +84,65 @@ static const char *DecalAttenuationVertexProgramCode =
MUL o[COL0].w, v[3], R0.w; \n\
END \n";
static NL3D::CVertexProgram DecalAttenuationVertexProgram(DecalAttenuationVertexProgramCode);
class CVertexProgramDecalAttenuation : public CVertexProgram
{
public:
struct CIdx
{
// 0-3 mvp
uint WorldToUV0; // 4
uint WorldToUV1; // 5
uint RefCamDist; // 6
uint DistScaleBias; // 7
uint Diffuse; // 8
// 9
// 10
uint BlendScale; // 11
};
CVertexProgramDecalAttenuation()
{
// nelvp
{
CSource *source = new CSource();
source->Profile = nelvp;
source->DisplayName = "nelvp/DecalAttenuation";
source->setSourcePtr(DecalAttenuationVertexProgramCode);
source->ParamIndices["modelViewProjection"] = 0;
source->ParamIndices["worldToUV0"] = 4;
source->ParamIndices["worldToUV1"] = 5;
source->ParamIndices["refCamDist"] = 6;
source->ParamIndices["distScaleBias"] = 7;
source->ParamIndices["diffuse"] = 8;
source->ParamIndices["blendScale"] = 11;
addSource(source);
}
// TODO_VP_GLSL
}
~CVertexProgramDecalAttenuation()
{
}
virtual void buildInfo()
{
m_Idx.WorldToUV0 = getUniformIndex("worldToUV0");
nlassert(m_Idx.WorldToUV0 != ~0);
m_Idx.WorldToUV1 = getUniformIndex("worldToUV1");
nlassert(m_Idx.WorldToUV1 != ~0);
m_Idx.RefCamDist = getUniformIndex("refCamDist");
nlassert(m_Idx.RefCamDist != ~0);
m_Idx.DistScaleBias = getUniformIndex("distScaleBias");
nlassert(m_Idx.DistScaleBias != ~0);
m_Idx.Diffuse = getUniformIndex("diffuse");
nlassert(m_Idx.Diffuse != ~0);
m_Idx.BlendScale = getUniformIndex("blendScale");
nlassert(m_Idx.BlendScale != ~0);
}
inline const CIdx &idx() const { return m_Idx; }
private:
CIdx m_Idx;
};
static NLMISC::CSmartPtr<CVertexProgramDecalAttenuation> DecalAttenuationVertexProgram;
typedef CShadowPolyReceiver::CRGBAVertex CRGBAVertex;
@ -92,6 +150,10 @@ typedef CShadowPolyReceiver::CRGBAVertex CRGBAVertex;
// ****************************************************************************
CDecal::CDecal()
{
if (!DecalAttenuationVertexProgram)
{
DecalAttenuationVertexProgram = new CVertexProgramDecalAttenuation();
}
_ShadowMap = new CShadowMap(&(((CSceneUser *) Scene)->getScene().getRenderTrav().getShadowMapManager()));
_Material.initUnlit();
_Diffuse = CRGBA::White;
@ -303,6 +365,7 @@ void CDecal::renderTriCache(NL3D::IDriver &drv, NL3D::CShadowPolyReceiver &/*
drv.setupModelMatrix(modelMat);
if (useVertexProgram)
{
CVertexProgramDecalAttenuation *program = DecalAttenuationVertexProgram;
{
CVertexBufferReadWrite vba;
_VB.setNumVertices((uint32)_TriCache.size());
@ -310,16 +373,16 @@ void CDecal::renderTriCache(NL3D::IDriver &drv, NL3D::CShadowPolyReceiver &/*
memcpy(vba.getVertexCoordPointer(), &_TriCache[0], sizeof(CRGBAVertex) * _TriCache.size());
}
drv.activeVertexBuffer(_VB);
drv.setConstantMatrix(0, NL3D::IDriver::ModelViewProjection, NL3D::IDriver::Identity);
drv.setConstant(4, _WorldToUVMatrix[0][0], _WorldToUVMatrix[1][0], _WorldToUVMatrix[2][0], _WorldToUVMatrix[3][0]);
drv.setConstant(5, _WorldToUVMatrix[0][1], _WorldToUVMatrix[1][1], _WorldToUVMatrix[2][1], _WorldToUVMatrix[3][1]);
drv.setConstant(8, _Diffuse.R * (1.f / 255.f), _Diffuse.G * (1.f / 255.f), _Diffuse.B * (1.f / 255.f), 1.f);
drv.setUniformMatrix(IDriver::VertexProgram, program->getUniformIndex(CProgramIndex::ModelViewProjection), NL3D::IDriver::ModelViewProjection, NL3D::IDriver::Identity);
drv.setUniform4f(IDriver::VertexProgram, program->idx().WorldToUV0, _WorldToUVMatrix[0][0], _WorldToUVMatrix[1][0], _WorldToUVMatrix[2][0], _WorldToUVMatrix[3][0]);
drv.setUniform4f(IDriver::VertexProgram, program->idx().WorldToUV1, _WorldToUVMatrix[0][1], _WorldToUVMatrix[1][1], _WorldToUVMatrix[2][1], _WorldToUVMatrix[3][1]);
drv.setUniform4f(IDriver::VertexProgram, program->idx().Diffuse, _Diffuse.R * (1.f / 255.f), _Diffuse.G * (1.f / 255.f), _Diffuse.B * (1.f / 255.f), 1.f);
const NLMISC::CVector &camPos = MainCam.getMatrix().getPos();
drv.setConstant(6, camPos.x - _RefPosition.x, camPos.y - _RefPosition.y, camPos.z - _RefPosition.z, 1.f);
drv.setUniform4f(IDriver::VertexProgram, program->idx().RefCamDist, camPos.x - _RefPosition.x, camPos.y - _RefPosition.y, camPos.z - _RefPosition.z, 1.f);
// bottom & top blend
float bottomBlendScale = 1.f / favoid0(_BottomBlendZMax - _BottomBlendZMin);
float topBlendScale = 1.f / favoid0(_TopBlendZMin - _TopBlendZMax);
drv.setConstant(11, bottomBlendScale, bottomBlendScale * (_RefPosition.z - _BottomBlendZMin),
drv.setUniform4f(IDriver::VertexProgram, program->idx().BlendScale, bottomBlendScale, bottomBlendScale * (_RefPosition.z - _BottomBlendZMin),
topBlendScale, topBlendScale * (_RefPosition.z - _TopBlendZMax));
//
static volatile bool wantSimpleMat = false;
@ -560,12 +623,12 @@ void CDecalRenderList::renderAllDecals()
NL3D::IDriver *drvInternal = ((CDriverUser *) Driver)->getDriver();
//
static volatile bool forceNoVertexProgram = false;
if (drvInternal->isVertexProgramSupported() && !forceNoVertexProgram)
if (!forceNoVertexProgram && drvInternal->compileVertexProgram(DecalAttenuationVertexProgram))
{
//drvInternal->setConstantMatrix(0, NL3D::IDriver::ModelViewProjection, NL3D::IDriver::Identity);
drvInternal->setConstant(7, _DistScale, _DistBias, 0.f, 1.f);
drvInternal->activeVertexProgram(DecalAttenuationVertexProgram);
//drvInternal->setCons/tantMatrix(0, NL3D::IDriver::ModelViewProjection, NL3D::IDriver::Identity);
drvInternal->setUniform4f(IDriver::VertexProgram, DecalAttenuationVertexProgram->idx().DistScaleBias, _DistScale, _DistBias, 0.f, 1.f);
useVertexProgram = true;
drvInternal->activeVertexProgram(&DecalAttenuationVertexProgram);
}
else
{

View file

@ -26,6 +26,8 @@ using namespace NLMISC;
// ***************************************************************************
// Main System
NL3D::UDriver *Driver = 0; // The main 3D Driver
NL3D::IStereoDisplay *StereoDisplay = NULL; // Stereo display
NL3D::IStereoHMD *StereoHMD = NULL; // Head mount display
CSoundManager *SoundMngr = 0; // the sound manager
NL3D::UMaterial GenericMat; // Generic Material
NL3D::UTextContext *TextContext = 0; // Context for all the text in the client.

View file

@ -40,6 +40,8 @@ namespace NL3D
class UMaterial;
class UTextContext;
class UWaterEnvMap;
class IStereoDisplay;
class IStereoHMD;
}
class CEntityAnimationManager;
@ -77,6 +79,8 @@ const float ExtraZoneLoadingVision = 100.f;
// ***************************************************************************
// Main System
extern NL3D::UDriver *Driver; // The main 3D Driver
extern NL3D::IStereoDisplay *StereoDisplay; // Stereo display
extern NL3D::IStereoHMD *StereoHMD; // Head mount display
extern CSoundManager *SoundMngr; // the sound manager
extern NL3D::UMaterial GenericMat; // Generic Material
extern NL3D::UTextContext *TextContext; // Context for all the text in the client.

View file

@ -39,6 +39,7 @@
#include "nel/3d/u_driver.h"
#include "nel/3d/u_text_context.h"
#include "nel/3d/u_shape_bank.h"
#include "nel/3d/stereo_hmd.h"
// Net.
#include "nel/net/email.h"
// Ligo.
@ -46,6 +47,7 @@
// Std.
#include <fstream>
#include <sstream>
// Game Share
#include "game_share/ryzom_version.h"
// Client
@ -792,6 +794,59 @@ void prelogInit()
// Check driver version
checkDriverVersion();
// Initialize the VR devices (even more important than the most important part of the client)
nmsg = "Initializing VR devices...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
if (ClientCfg.VREnable)
{
nldebug("VR [C]: Enabled");
std::vector<NL3D::CStereoDeviceInfo> devices;
IStereoDisplay::listDevices(devices);
for (std::vector<NL3D::CStereoDeviceInfo>::iterator it(devices.begin()), end(devices.end()); it != end; ++it)
{
std::stringstream name;
name << std::string("[") << it->Serial << "] [" << IStereoDisplay::getLibraryName(it->Library) << " - " << it->Manufacturer << " - " << it->ProductName << "]";
nlinfo("VR [C]: Stereo Display: %s", name.str().c_str());
}
CStereoDeviceInfo *deviceInfo = NULL;
if (ClientCfg.VRDisplayDevice == std::string("Auto")
&& devices.begin() != devices.end())
{
deviceInfo = &devices[0];
}
else
{
for (std::vector<NL3D::CStereoDeviceInfo>::iterator it(devices.begin()), end(devices.end()); it != end; ++it)
{
std::stringstream name;
name << IStereoDisplay::getLibraryName(it->Library) << " - " << it->Manufacturer << " - " << it->ProductName;
if (name.str() == ClientCfg.VRDisplayDevice)
deviceInfo = &(*it);
if (ClientCfg.VRDisplayDeviceId == it->Serial)
break;
}
}
if (deviceInfo)
{
nlinfo("VR [C]: Create VR stereo display device");
StereoDisplay = IStereoDisplay::createDevice(*deviceInfo);
if (StereoDisplay)
{
if (deviceInfo->Class == CStereoDeviceInfo::StereoHMD)
{
nlinfo("VR [C]: Stereo display device is a HMD");
StereoHMD = static_cast<IStereoHMD *>(StereoDisplay);
}
}
}
}
else
{
nldebug("VR [C]: NOT Enabled");
}
IStereoDisplay::releaseUnusedLibraries();
// Create the driver (most important part of the client).
nmsg = "Creating 3d driver...";
ProgressBar.newMessage ( ClientCfg.buildLoadingString(nmsg) );
@ -860,6 +915,11 @@ void prelogInit()
Driver->setSwapVBLInterval(1);
else
Driver->setSwapVBLInterval(0);
if (StereoDisplay)
{
// override mode TODO
}
// Set the mode of the window.
if (!Driver->setDisplay (mode, false))
@ -1102,6 +1162,12 @@ void prelogInit()
// init bloom effect
CBloomEffect::getInstance().init(driver != UDriver::Direct3d);
if (StereoDisplay)
{
// Init stereo display resources
StereoDisplay->setDriver(Driver);
}
nlinfo ("PROFILE: %d seconds for prelogInit", (uint32)(ryzomGetLocalTime ()-initStart)/1000);

View file

@ -542,10 +542,12 @@ void renderSceneScreenShot (uint left, uint right, uint top, uint bottom, uint s
{
CCameraBackup cbScene = setupCameraForScreenshot(*Scene, left, right, top, bottom, screenShotWidth, screenShotHeight);
CCameraBackup cbCanopy = setupCameraForScreenshot(*SceneRoot, left, right, top, bottom, screenShotWidth, screenShotHeight);
commitCamera();
// sky setup are copied from main scene before rendering so no setup done here
renderAll(ClientCfg.ScreenShotFullDetail);
renderScene(ClientCfg.ScreenShotFullDetail, ClientCfg.Bloom);
restoreCamera(*Scene, cbScene);
restoreCamera(*SceneRoot, cbCanopy);
commitCamera();
}
// ***************************************************************************

View file

@ -95,11 +95,11 @@ public:
private:
// renderAll is called in main loop. It can called beginRenderLandscapePolyPart and renderLandscapePolyPart
// renderScene is called in main loop. It can called beginRenderLandscapePolyPart and renderLandscapePolyPart
// methods.
friend void renderAll(bool);
friend void renderScene();
// Enable stencil test and initialize function and operation of stencil at the beginning of renderAll method,
// 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.
// The eighth bit will be written with a 0 during next render to mark stencil buffer parts which will
// support Shadow Volume algorithm.

File diff suppressed because it is too large Load diff

View file

@ -29,9 +29,13 @@ const uint NUM_MISSION_OPTIONS = 8;
bool mainLoop();
// render all
void renderAll(bool forceFullDetail = false);
void renderScene();
void renderScene(bool forceFullDetail, bool bloom);
void setDefaultChatWindow(CChatWindow *defaultChatWindow);
// Commit sky scene camera for rendering
void commitCamera();
void updateDayNightCycleHour();

View file

@ -0,0 +1,774 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
#include <nel/misc/types_nl.h>
#include "main_loop_debug.h"
#include <nel/3d/u_text_context.h>
#include <nel/gui/lua_ihm.h>
#include "game_share/ryzom_version.h"
#include "global.h"
#include "client_cfg.h"
#include "user_entity.h"
#include "debug_client.h"
#include "entities.h"
#include "motion/user_controls.h"
#include "pacs_client.h"
#include "sound_manager.h"
#include "view.h"
#include "prim_file.h"
#include "weather.h"
#include "light_cycle_manager.h"
#include "net_manager.h"
#include "ping.h"
#include "world_database_manager.h"
#include "continent_manager.h"
#include "client_sheets/weather_function_params_sheet.h"
#include "weather_manager_client.h"
#include "fog_map.h"
#include "misc.h"
#include "interface_v3/interface_manager.h"
using namespace NLMISC;
using namespace NL3D;
using namespace NLGUI;
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
extern std::set<std::string> LodCharactersNotFound;
extern uint32 NbDatabaseChanges;
extern CFogState MainFogState;
extern CPing Ping;
extern bool Filter3D[RYZOM_MAX_FILTER_3D];
//namespace /* anonymous */ {
NLMISC::CValueSmoother smoothFPS;
NLMISC::CValueSmoother moreSmoothFPS(64);
//} /* anonymous namespace */
//---------------------------------------------------
// displayDebug :
// Display some debug infos.
//---------------------------------------------------
void displayDebug()
{
float lineStep = ClientCfg.DebugLineStep;
float line;
// Initialize Pen //
//----------------//
// Create a shadow when displaying a text.
TextContext->setShaded(true);
// Set the font size.
TextContext->setFontSize(ClientCfg.DebugFontSize);
// Set the text color
TextContext->setColor(ClientCfg.DebugFontColor);
// TOP LEFT //
//----------//
TextContext->setHotSpot(UTextContext::TopLeft);
line = 0.9f;
// FPS and Ms per frame
{
// smooth across frames.
double deltaTime = smoothFPS.getSmoothValue ();
// FPS and Ms per frame
if(deltaTime != 0.f)
TextContext->printfAt(0.f, line,"%.1f fps", 1.f/deltaTime);
else
TextContext->printfAt(0.f, line,"%.1f fps", 0.f);
TextContext->printfAt(0.1f, line, "%d ms", (uint)(deltaTime*1000));
}
line -= lineStep;
line -= lineStep;
// USER
// Front
TextContext->printfAt(0.0f, line, " %f (%f,%f,%f) front", atan2(UserEntity->front().y, UserEntity->front().x), UserEntity->front().x, UserEntity->front().y, UserEntity->front().z);
line -= lineStep;
// Dir
TextContext->printfAt(0.0f, line, " %f (%f,%f,%f) dir", atan2(UserEntity->dir().y, UserEntity->dir().x), UserEntity->dir().x, UserEntity->dir().y, UserEntity->dir().z);
line -= lineStep;
// NB Stage
TextContext->printfAt(0.0f, line, " NB Stage: %d", UserEntity->nbStage());
line -= lineStep;
// NB Animation FXs still remaining in the remove list.
TextContext->printfAt(0.0f, line, " NB FXs to remove: %d", UserEntity->nbAnimFXToRemove());
line -= lineStep;
// Mode.
TextContext->printfAt(0.0f, line, " Mode: %d (%s)", (sint)UserEntity->mode(), MBEHAV::modeToString(UserEntity->mode()).c_str());
line -= lineStep;
// Behaviour.
TextContext->printfAt(0.0f, line, " Behaviour: %d (%s)", (sint)UserEntity->behaviour(), MBEHAV::behaviourToString(UserEntity->behaviour()).c_str());
line -= lineStep;
// Display the target mount.
TextContext->printfAt(0.0f, line, " Mount: %d", UserEntity->mount());
line -= lineStep;
// Display the target rider.
TextContext->printfAt(0.0f, line, " Rider: %d", UserEntity->rider());
line -= lineStep;
// Display the current animation name.
TextContext->printfAt(0.0f, line, " Current Animation Name: %s", UserEntity->currentAnimationName().c_str());
line -= lineStep;
// Display the current move animation set name.
TextContext->printfAt(0.0f, line, " Current AnimationSet Name (MOVE): %s", UserEntity->currentAnimationSetName(MOVE).c_str());
line -= lineStep;
// Display Missing Animations
if(::CAnimation::MissingAnim.empty() == false)
{
TextContext->printfAt(0.0f, line, " '%u' Missing Animations, 1st: '%s'", ::CAnimation::MissingAnim.size(), (*(::CAnimation::MissingAnim.begin())).c_str());
line -= lineStep;
}
// Display Missing LoD
if(LodCharactersNotFound.empty() == false)
{
TextContext->printfAt(0.0f, line, " '%u' Missing LoD, 1st: '%s'", LodCharactersNotFound.size(), (*(LodCharactersNotFound.begin())).c_str());
line -= lineStep;
}
// Watched Entity
line -= lineStep;
// Now Displaying the selection.
TextContext->printfAt(0.0f, line, "--*** Watched entity ***--");
line -= lineStep;
// Display information about the debug entity slot.
if(WatchedEntitySlot != CLFECOMMON::INVALID_SLOT)
{
// Get a pointer on the target.
CEntityCL *watchedEntity = EntitiesMngr.entity(WatchedEntitySlot);
if(watchedEntity)
{
// Display Debug Information about the Selection.
watchedEntity->displayDebug(0.0f, line, -lineStep);
// Distance of the target
CVectorD diffvector = UserEntity->pos() - watchedEntity->pos();
TextContext->printfAt(0.0f, line, " Distance: %10.2f (Manhattan: %.2f)", diffvector.norm(), fabs(diffvector.x) + fabs(diffvector.y) );
line -= lineStep;
}
// Target not allocated
else
{
TextContext->printfAt(0.0f, line, "Not allocated (%d)", WatchedEntitySlot);
line -= lineStep;
}
}
// No Target
else
{
TextContext->printfAt(0.0f, line, "None");
line -= lineStep;
}
/* Ca rame grave !
uint nMem = NLMEMORY::GetAllocatedMemory();
line -= lineStep;
TextContext->printfAt(0.0f, line, "Mem Used: %d",nMem);*/
// 3D Filters information:
#ifdef _PROFILE_ON_
line-= lineStep;
TextContext->printfAt(0.0f, line, "3D Filters:");
line-= lineStep;
TextContext->printfAt(0.0f, line, "MeshNoVP: %s", Filter3D[FilterMeshNoVP]?"Ok":"NOT RENDERED!");
line-= lineStep;
TextContext->printfAt(0.0f, line, "MeshVP: %s", Filter3D[FilterMeshVP]?"Ok":"NOT RENDERED!");
line-= lineStep;
TextContext->printfAt(0.0f, line, "FXs: %s", Filter3D[FilterFXs]?"Ok":"NOT RENDERED!");
line-= lineStep;
if (Landscape)
{
TextContext->printfAt(0.0f, line, "Landscape: %s", Filter3D[FilterLandscape]?"Ok":"NOT RENDERED!");
line-= lineStep;
}
else
{
TextContext->printfAt(0.0f, line, "Landscape not enabled");
}
TextContext->printfAt(0.0f, line, "Vegetable: %s", Filter3D[FilterVegetable]?"Ok":"NOT RENDERED!");
line-= lineStep;
TextContext->printfAt(0.0f, line, "Skeleton: %s", Filter3D[FilterSkeleton]?"Ok":"NOT RENDERED!");
line-= lineStep;
TextContext->printfAt(0.0f, line, "Water: %s", Filter3D[FilterWater]?"Ok":"NOT RENDERED!");
line-= lineStep;
TextContext->printfAt(0.0f, line, "Cloud: %s", Filter3D[FilterCloud]?"Ok":"NOT RENDERED!");
line-= lineStep;
TextContext->printfAt(0.0f, line, "CoarseMesh: %s", Filter3D[FilterCoarseMesh]?"Ok":"NOT RENDERED!");
line-= lineStep;
TextContext->printfAt(0.0f, line, "Sky: %s", Filter3D[FilterSky]?"Ok":"NOT RENDERED!");
line-= lineStep;
// Materials Infos
TextContext->printfAt(0.0f, line, "SetupedMatrix: %d", Driver->profileSetupedModelMatrix() );
line-= lineStep;
TextContext->printfAt(0.0f, line, "SetupedMaterials: %d", Driver->profileSetupedMaterials() );
line-= lineStep;
// Display camera cluster system
TextContext->printfAt(0.0f, line, "ClusterSystem: %p", MainCam.getClusterSystem() );
line-= 2 * lineStep;
// Lua stuffs
CInterfaceManager *pIM = CInterfaceManager::getInstance();
TextContext->printfAt(0.0f, line, "Lua mem (kb) : %d / %d", CLuaManager::getInstance().getLuaState()->getGCCount(), CLuaManager::getInstance().getLuaState()->getGCThreshold());
line-= lineStep;
TextContext->printfAt(0.0f, line, "Lua stack size = %d", CLuaManager::getInstance().getLuaState()->getTop());
line-= lineStep;
#endif
// TOP LEFT //
//-----------//
TextContext->setHotSpot(UTextContext::TopLeft);
line = 1.f;
string str;
#if FINAL_VERSION
str = "FV";
#else
str = "DEV";
#endif
if(ClientCfg.ExtendedCommands)
str += "_E";
str += " "RYZOM_VERSION;
TextContext->printfAt(0.f, line, "Version %s", str.c_str());
// TOP MIDDLE //
//------------//
TextContext->setHotSpot(UTextContext::MiddleTop);
line = 1.f;
// Motion Mode
TextContext->printfAt(0.5f, line, "%s", UserControls.modeStr().c_str());
line -= lineStep;
// TOP RIGHT //
//-----------//
TextContext->setHotSpot(UTextContext::TopRight);
line = 1.f;
//// 3D Infos
// Video mem allocated.
TextContext->printfAt(1.f, line, "Video mem. : %f", Driver->profileAllocatedTextureMemory()/(1024.f*1024.f));
line -= lineStep;
// Video mem used since last swapBuffers().
TextContext->printfAt(1.f, line, "Video mem. since last swap buffer: %f", Driver->getUsedTextureMemory()/(1024.f*1024.f));
line -= lineStep;
// Get the last face count asked from the main scene before reduction.
TextContext->printfAt(1.f, line, "Nb Skin Face Asked: %f", Scene->getGroupNbFaceAsked("Skin"));
line -= lineStep;
TextContext->printfAt(1.f, line, "Nb Fx Face Asked: %f", Scene->getGroupNbFaceAsked("Fx"));
line -= lineStep;
// All Triangles In
CPrimitiveProfile pIn;
CPrimitiveProfile pOut;
Driver->profileRenderedPrimitives(pIn, pOut);
TextContext->printfAt(1.f, line, "Tri In : %d", pIn.NTriangles+2*pIn.NQuads);
line -= lineStep;
// All Triangles Out
TextContext->printfAt(1.f, line, "Tri Out : %d", pOut.NTriangles+2*pIn.NQuads);
line -= lineStep;
// Current Cluster
string strPos;
// Check there is a PACS Primitive before using it.
if(UserEntity->getPrimitive() && GR)
{
UGlobalPosition gPos;
UserEntity->getPrimitive()->getGlobalPosition(gPos, dynamicWI);
string strPos = GR->getIdentifier(gPos);
}
else
strPos = "No Primitive";
TextContext->printfAt(1.f, line, "Cluster : %s", strPos.c_str());
line -= lineStep;
//// SOUND Infos
line -= lineStep;
if(SoundMngr)
{
TextContext->printfAt(1.f, line, "Sound source instance: %u", SoundMngr->getSourcesInstanceCount());
line -= lineStep;
TextContext->printfAt(1.f, line, "Logical playing SoundSource: %u", SoundMngr->getMixer()->getPlayingSourcesCount ());
line -= lineStep;
TextContext->printfAt(1.f, line, "Audio tracks: %u/%u", SoundMngr->getMixer()->getUsedTracksCount(), SoundMngr->getMixer()->getPolyphony());
line -= lineStep;
if (SoundMngr->getMixer()->getMutedPlayingSourcesCount() > 0)
{
TextContext->printfAt(1.f, line, "Source muted: %u !", SoundMngr->getMixer()->getMutedPlayingSourcesCount());
line -= lineStep;
}
TextContext->printfAt(1.f, line, "Samples in memory: %g MB", SoundMngr->getLoadingSamplesSize() / (1024.0f*1024.0f));
line -= lineStep;
}
// BOTTOM RIGHT //
//--------------//
TextContext->setHotSpot(UTextContext::BottomRight);
line = 0.f;
//// POSITION
CVector postmp = View.viewPos();
// Pos
TextContext->printfAt(1.f, line, "Position : %d %d %d",(int)postmp.x,(int)postmp.y,(int)postmp.z);
line += lineStep;
// Body Heading
TextContext->printfAt(1.f, line, "Front : %.2f %.2f %.2f", UserEntity->front().x, UserEntity->front().y, UserEntity->front().z);
line += lineStep;
// Speed
TextContext->printfAt(1.f, line, "Speed : %.2f", (float) UserEntity->speed());
line += lineStep;
// Zone
if (!ClientCfg.Light)
{
if (Landscape)
{
TextContext->printfAt(1.f, line, "Zone: %s", Landscape->getZoneName(postmp).c_str());
line += lineStep;
}
}
// Prim File
string primFile = PrimFiles.getCurrentPrimitive ();
if (!primFile.empty ())
{
TextContext->printfAt(1.f, line, "Prim File: %s", primFile.c_str ());
line += lineStep;
}
//// CONNECTION
line += lineStep;
// Ryzom Day.
TextContext->printfAt(1.f, line, "Ryzom Day : %d", RT.getRyzomDay());
line += lineStep;
// hour in the game
float dayNightCycleHour = (float)RT.getRyzomTime();
TextContext->printfAt(1.f, line, "Ryzom Time : %2u:%02u", int(dayNightCycleHour), int((dayNightCycleHour-int(dayNightCycleHour))*60.0f));
line += lineStep;
// light hour in the game, used to display te day/night
TextContext->printfAt(1.f, line, "Ryzom Light Time : %2u:%02u (%s)", int(DayNightCycleHour), int((DayNightCycleHour-int(DayNightCycleHour))*60.0f), LightCycleManager.getStateString().c_str());
line += lineStep;
// Server GameCycle
TextContext->printfAt(1.f, line, "Server GameCycle : %u", (uint)NetMngr.getCurrentServerTick());
line += lineStep;
// Current GameCycle
TextContext->printfAt(1.f, line, "Current GameCycle : %u", (uint)NetMngr.getCurrentClientTick());
line += lineStep;
// Current GameCycle
TextContext->printfAt(1.f, line, "Ms per Cycle : %d", NetMngr.getMsPerTick());
line += lineStep;
// Packet Loss
TextContext->printfAt(1.f, line, "Packet Loss : %.1f %%", NetMngr.getMeanPacketLoss()*100.0f);
line += lineStep;
// Packet Loss
TextContext->printfAt(1.f, line, "Packets Lost : %u", NetMngr.getTotalLostPackets());
line += lineStep;
// Mean Upload
TextContext->printfAt(1.f, line, "Mean Upld : %.3f kbps", NetMngr.getMeanUpload());
line += lineStep;
// Mean Download
TextContext->printfAt(1.f, line, "Mean Dnld : %.3f kbps", NetMngr.getMeanDownload());
line += lineStep;
// Mean Download
TextContext->printfAt(1.f, line, "Nb in Vision : %d(%d,%d,%d)",
EntitiesMngr.nbEntitiesAllocated(),
EntitiesMngr.nbUser(),
EntitiesMngr.nbPlayer(),
EntitiesMngr.nbChar());
line += lineStep;
// Number of database changes
TextContext->printfAt(1.f, line, "DB Changes : %u", NbDatabaseChanges );
line += lineStep;
// Ping
TextContext->printfAt(1.f, line, "DB Ping : %u ms", Ping.getValue());
line += lineStep;
// Manual weather setup
{
if(ContinentMngr.cur()) // Only usable if there is a continent loaded.
{
if (!ForceTrueWeatherValue)
{
const CWeatherFunction &wf = ContinentMngr.cur()->WeatherFunction[CurrSeason];
float wv;
if (ClientCfg.ManualWeatherSetup)
{
wv = std::max(wf.getNumWeatherSetups() - 1, 0u) * ManualWeatherValue;
}
else
{
wv = std::max(wf.getNumWeatherSetups() - 1, 0u) * ::getBlendedWeather(RT.getRyzomDay(), RT.getRyzomTime(), *WeatherFunctionParams, ContinentMngr.cur()->WeatherFunction);
}
const CWeatherSetup *ws = wf.getWeatherSetup((uint) floorf(wv));
std::string name0 = ws ? NLMISC::CStringMapper::unmap(ws->SetupName) : "???";
ws = wf.getWeatherSetup(std::min((uint) (floorf(wv) + 1), wf.getNumWeatherSetups() - 1));
std::string name1 = ws ? NLMISC::CStringMapper::unmap(ws->SetupName) : "???";
TextContext->printfAt(1.f, line, "Weather value : %.02f : %s -> %s", ws ? wv : 0.f, name0.c_str(), name1.c_str());
line += lineStep;
}
else
{
TextContext->printfAt(1.f, line, "Weather value : %.02f", WeatherManager.getWeatherValue() * std::max(ContinentMngr.cur()->WeatherFunction[CurrSeason].getNumWeatherSetups() - 1, 0u));
line += lineStep;
TextContext->printfAt(1.f, line, "TEST WEATHER FUNCTION");
line += lineStep;
}
// season
TextContext->printfAt(1.f, line, "Season : %s", EGSPD::CSeason::toString(CurrSeason).c_str());
line += lineStep;
}
}
// fog dist
if (ContinentMngr.cur())
{
TextContext->printfAt(1.f, line, "Continent fog min near = %.1f, max far = %.1f", ContinentMngr.cur()->FogStart, ContinentMngr.cur()->FogEnd);
line += lineStep;
CFogState tmpFog;
ContinentMngr.getFogState(MainFog, LightCycleManager.getLightLevel(), LightCycleManager.getLightDesc().DuskRatio, LightCycleManager.getState(), View.viewPos(), tmpFog);
TextContext->printfAt(1.f, line, "Continent fog curr near = %.1f, curr far = %.1f", tmpFog.FogStartDist, tmpFog.FogEndDist);
line += lineStep;
}
const CWeatherState &ws = WeatherManager.getCurrWeatherState();
TextContext->printfAt(1.f, line, "Weather fog near = %.1f, far = %.1f", ws.FogNear[MainFog], ws.FogFar[MainFog]);
line += lineStep;
TextContext->printfAt(1.f, line, "Final fog near = %.1f, far = %.1f", MainFogState.FogStartDist, MainFogState.FogEndDist);
line += lineStep;
float left, right, bottom, top, znear, zfar;
Scene->getCam().getFrustum(left, right, bottom, top, znear, zfar);
TextContext->printfAt(1.f, line, "Clip near = %.1f, far = %.1f", znear, zfar);
line += lineStep;
// Connection states
TextContext->printfAt(1.f, line, "State : %s", NetMngr.getConnectionStateCStr() );
line += lineStep;
// UGlobalPosition globalPos;
// UserEntity->getPrimitive()->getGlobalPosition(globalPos, dynamicWI);
// uint32 material = GR->getMaterial( globalPos );
// TextContext->printfAt(0.5f,0.5f,"Material : %d Gpos=(inst=%d,surf=%d,x=%.2f,y=%.2f",material, globalPos.InstanceId, globalPos.LocalPosition.Surface, globalPos.LocalPosition.Estimation.x, globalPos.LocalPosition.Estimation.y);
// No more shadow when displaying a text.
TextContext->setShaded(false);
}// displayDebug //
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
//---------------------------------------------------
// displayDebug :
// Display some debug infos.
//---------------------------------------------------
void displayDebugFps()
{
float lineStep = ClientCfg.DebugLineStep;
float line;
// Initialize Pen //
//----------------//
// Create a shadow when displaying a text.
TextContext->setShaded(true);
// Set the font size.
TextContext->setFontSize(ClientCfg.DebugFontSize);
// Set the text color
TextContext->setColor(ClientCfg.DebugFontColor);
// TOP LEFT //
//----------//
TextContext->setHotSpot(UTextContext::TopLeft);
line = 0.9f;
// Ms per frame
{
float spf = smoothFPS.getSmoothValue ();
// Ms per frame
TextContext->printfAt(0.1f, line, "FPS %.1f ms - %.1f fps", spf*1000, 1.f/spf);
line-= lineStep;
// More Smoothed Ms per frame
spf = moreSmoothFPS.getSmoothValue ();
TextContext->printfAt(0.1f, line, "Smoothed FPS %.1f ms - %.1f fps", spf*1000, 1.f/spf);
line-= lineStep;
}
}
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
static NLMISC::CRefPtr<CInterfaceElement> HighlightedDebugUI;
// displayDebug :
// Display information about ui elements that are under the mouse
//---------------------------------------------------
void displayDebugUIUnderMouse()
{
float lineStep = ClientCfg.DebugLineStep;
float line;
// Initialize Pen //
//----------------//
// Create a shadow when displaying a text.
TextContext->setShaded(true);
// Set the font size.
TextContext->setFontSize(ClientCfg.DebugFontSize);
// TOP LEFT //
//----------//
TextContext->setHotSpot(UTextContext::TopLeft);
line = 0.9f;
CInterfaceManager *pIM = CInterfaceManager::getInstance();
// for now only accessible with R2ED
if (ClientCfg.R2EDEnabled)
{
TextContext->setColor(CRGBA::Cyan);
TextContext->printfAt(0.1f, line, "Press default key (ctrl+shift+A) to cycle prev");
line-= lineStep;
TextContext->printfAt(0.1f, line, "Press default key (ctrl+shift+Q) to cycle next");
line-= lineStep;
TextContext->printfAt(0.1f, line, "Press default key (ctrl+shift+W) to inspect element");
line-= 2 * lineStep;
}
//
const std::vector<CCtrlBase *> &rICL = CWidgetManager::getInstance()->getCtrlsUnderPointer ();
const std::vector<CInterfaceGroup *> &rIGL = CWidgetManager::getInstance()->getGroupsUnderPointer ();
// If previous highlighted element is found in the list, then keep it, else reset to first element
if (std::find(rICL.begin(), rICL.end(), HighlightedDebugUI) == rICL.end() &&
std::find(rIGL.begin(), rIGL.end(), HighlightedDebugUI) == rIGL.end())
{
if (!rICL.empty())
{
HighlightedDebugUI = rICL[0];
}
else
if (!rIGL.empty())
{
HighlightedDebugUI = rIGL[0];
}
else
{
HighlightedDebugUI = NULL;
}
}
//
TextContext->setColor(CRGBA::Green);
TextContext->printfAt(0.1f, line, "Controls under cursor ");
line -= lineStep * 1.4f;
TextContext->printfAt(0.1f, line, "----------------------");
line -= lineStep;
for(uint k = 0; k < rICL.size(); ++k)
{
if (rICL[k])
{
TextContext->setColor(rICL[k] != HighlightedDebugUI ? ClientCfg.DebugFontColor : CRGBA::Red);
TextContext->printfAt(0.1f, line, "id = %s, address = 0x%p, parent = 0x%p", rICL[k]->getId().c_str(), rICL[k], rICL[k]->getParent());
}
else
{
TextContext->setColor(CRGBA::Blue);
TextContext->printfAt(0.1f, line, "<NULL> control found !!!");
}
line-= lineStep;
}
//
TextContext->setColor(CRGBA::Green);
TextContext->printfAt(0.1f, line, "Groups under cursor ");
line -= lineStep * 1.4f;
TextContext->printfAt(0.1f, line, "----------------------");
line-= lineStep;
for(uint k = 0; k < rIGL.size(); ++k)
{
if (rIGL[k])
{
TextContext->setColor(rIGL[k] != HighlightedDebugUI ? ClientCfg.DebugFontColor : CRGBA::Red);
TextContext->printfAt(0.1f, line, "id = %s, address = 0x%p, parent = 0x%p", rIGL[k]->getId().c_str(), rIGL[k], rIGL[k]->getParent());
}
else
{
TextContext->setColor(CRGBA::Blue);
TextContext->printfAt(0.1f, line, "<NULL> group found !!!");
}
line-= lineStep;
}
}
// get all element under the mouse in a single vector
static void getElementsUnderMouse(std::vector<CInterfaceElement *> &ielem)
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
const std::vector<CCtrlBase *> &rICL = CWidgetManager::getInstance()->getCtrlsUnderPointer();
const std::vector<CInterfaceGroup *> &rIGL = CWidgetManager::getInstance()->getGroupsUnderPointer();
ielem.clear();
ielem.insert(ielem.end(), rICL.begin(), rICL.end());
ielem.insert(ielem.end(), rIGL.begin(), rIGL.end());
}
class CHandlerDebugUiPrevElementUnderMouse : public IActionHandler
{
virtual void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */)
{
std::vector<CInterfaceElement *> ielem;
getElementsUnderMouse(ielem);
for(uint k = 0; k < ielem.size(); ++k)
{
if (HighlightedDebugUI == ielem[k])
{
HighlightedDebugUI = ielem[k == 0 ? ielem.size() - 1 : k - 1];
return;
}
}
}
};
REGISTER_ACTION_HANDLER( CHandlerDebugUiPrevElementUnderMouse, "debug_ui_prev_element_under_mouse");
class CHandlerDebugUiNextElementUnderMouse : public IActionHandler
{
virtual void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */)
{
std::vector<CInterfaceElement *> ielem;
getElementsUnderMouse(ielem);
for(uint k = 0; k < ielem.size(); ++k)
{
if (HighlightedDebugUI == ielem[k])
{
HighlightedDebugUI = ielem[(k + 1) % ielem.size()];
return;
}
}
}
};
REGISTER_ACTION_HANDLER( CHandlerDebugUiNextElementUnderMouse, "debug_ui_next_element_under_mouse");
class CHandlerDebugUiDumpElementUnderMouse : public IActionHandler
{
virtual void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */)
{
if (HighlightedDebugUI == NULL) return;
CLuaState *lua = CLuaManager::getInstance().getLuaState();
if (!lua) return;
CLuaStackRestorer lsr(lua, 0);
CLuaIHM::pushUIOnStack(*lua, HighlightedDebugUI);
lua->pushGlobalTable();
CLuaObject env(*lua);
env["inspect"].callNoThrow(1, 0);
}
};
REGISTER_ACTION_HANDLER( CHandlerDebugUiDumpElementUnderMouse, "debug_ui_inspect_element_under_mouse");
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
//-----------------------------------------------
// Macro to Display a Text
//-----------------------------------------------
#define DISP_TEXT(x, text) \
/* Display the text at the right place */ \
TextContext->printfAt(x, line, text); \
/* Change the line */ \
line += lineStep; \
//---------------------------------------------------
// displayHelp :
// Display an Help.
//---------------------------------------------------
void displayHelp()
{
float line = 1.f;
float lineStep = -ClientCfg.HelpLineStep;
// Create a shadow when displaying a text.
TextContext->setShaded(true);
// Set the font size.
TextContext->setFontSize(ClientCfg.HelpFontSize);
// Set the text color
TextContext->setColor(ClientCfg.HelpFontColor);
line = 1.f;
TextContext->setHotSpot(UTextContext::TopLeft);
DISP_TEXT(0.0f, "SHIFT + F1 : This Menu")
DISP_TEXT(0.0f, "SHIFT + F2 : Display Debug Infos")
DISP_TEXT(0.0f, "SHIFT + F3 : Wire mode");
DISP_TEXT(0.0f, "SHIFT + F4 : Do not Render the Scene");
DISP_TEXT(0.0f, "SHIFT + F5 : Toogle Display OSD interfaces");
// DISP_TEXT(0.0f, "SHIFT + F6 : Not used");
DISP_TEXT(0.0f, "SHIFT + F7 : Compass Mode (User/Camera)");
DISP_TEXT(0.0f, "SHIFT + F8 : Camera Mode (INSERT to change your position)");
DISP_TEXT(0.0f, "SHIFT + F9 : Free Mouse");
DISP_TEXT(0.0f, "SHIFT + F10 : Take a Screen Shot (+CTRL) for jpg");
// DISP_TEXT(0.0f, "SHIFT + F11 : Test");
DISP_TEXT(0.0f, "SHIFT + ESCAPE : Quit");
DISP_TEXT(0.0f, "SHIFT + C : First/Third Person View");
line = 1.f;
TextContext->setHotSpot(UTextContext::TopRight);
DISP_TEXT(1.0f, "UP : FORWARD");
DISP_TEXT(1.0f, "DOWN : BACKWARD");
DISP_TEXT(1.0f, "LEFT : ROTATE LEFT");
DISP_TEXT(1.0f, "RIGHT : ROTATE RIGHT");
DISP_TEXT(1.0f, "CTRL + LEFT : STRAFE LEFT");
DISP_TEXT(1.0f, "CTRL + RIGHT : STRAFE RIGHT");
DISP_TEXT(1.0f, "END : Auto Walk");
DISP_TEXT(1.0f, "DELETE : Walk/Run");
DISP_TEXT(1.0f, "PG UP : Look Up");
DISP_TEXT(1.0f, "PG DOWN : Look Down");
// DISP_TEXT(1.0f, "CTRL + I : Inventory");
// DISP_TEXT(1.0f, "CTRL + C : Spells composition interface");
// DISP_TEXT(1.0f, "CTRL + S : Memorized Spells interface");
DISP_TEXT(1.0f, "CTRL + B : Show/Hide PACS Borders");
DISP_TEXT(1.0f, "CTRL + P : Player target himself");
DISP_TEXT(1.0f, "CTRL + D : Unselect target");
DISP_TEXT(1.0f, "CTRL + TAB : Next Chat Mode (say/shout");
DISP_TEXT(1.0f, "CTRL + R : Reload Client.cfg File");
// DISP_TEXT(1.0f, "CTRL + N : Toggle Night / Day lighting");
DISP_TEXT(1.0f, "CTRL + F2 : Profile on / off");
DISP_TEXT(1.0f, "CTRL + F3 : Movie Shooter record / stop");
DISP_TEXT(1.0f, "CTRL + F4 : Movie Shooter replay");
DISP_TEXT(1.0f, "CTRL + F5 : Movie Shooter save");
#ifndef NL_USE_DEFAULT_MEMORY_MANAGER
DISP_TEXT(1.0f, "CTRL + F6 : Save memory stat report");
#endif // NL_USE_DEFAULT_MEMORY_MANAGER
DISP_TEXT(1.0f, "CTRL + F7 : Show / hide prim file");
DISP_TEXT(1.0f, "CTRL + F8 : Change prim file UP");
DISP_TEXT(1.0f, "CTRL + F9 : Change prim file DOWN");
// No more shadow when displaying a text.
TextContext->setShaded(false);
}// displayHelp //
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
/* end of file */

View file

@ -0,0 +1,31 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
#ifndef CL_MAIN_LOOP_DEBUG_H
#define CL_MAIN_LOOP_DEBUG_H
#include <nel/misc/types_nl.h>
// Display some debug infos.
void displayDebug();
void displayDebugFps();
void displayDebugUIUnderMouse();
// Display an Help.
void displayHelp();
#endif // CL_MAIN_LOOP_DEBUG_H
/* end of file */

View file

@ -0,0 +1,226 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
#include <nel/misc/types_nl.h>
#include "main_loop_temp.h"
#include "global.h"
// tempDumpValidPolys
#include <nel/gui/interface_element.h>
#include <nel/gui/ctrl_polygon.h>
#include "interface_v3/interface_manager.h"
// tempDumpColPolys
#include <nel/3d/packed_world.h>
#include "r2/editor.h"
#include "user_entity.h"
#include <nel/3d/driver_user.h>
using namespace NLMISC;
using namespace NL3D;
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
// TMP TMP
void tempDumpValidPolys()
{
struct CPolyDisp : public CInterfaceElementVisitor
{
virtual void visitCtrl(CCtrlBase *ctrl)
{
CCtrlPolygon *cp = dynamic_cast<CCtrlPolygon *>(ctrl);
if (cp)
{
sint32 cornerX, cornerY;
cp->getParent()->getCorner(cornerX, cornerY, cp->getParentPosRef());
for(sint32 y = 0; y < (sint32) Screen.getHeight(); ++y)
{
for(sint32 x = 0; x < (sint32) Screen.getWidth(); ++x)
{
if (cp->contains(CVector2f((float) (x - cornerX), (float) (y - cornerY))))
{
((CRGBA *) &Screen.getPixels()[0])[x + (Screen.getHeight() - 1 - y) * Screen.getWidth()] = CRGBA::Magenta;
}
}
}
}
}
CBitmap Screen;
} polyDisp;
Driver->getBuffer(polyDisp.Screen);
CInterfaceManager::getInstance()->visit(&polyDisp);
COFile output("poly.tga");
polyDisp.Screen.writeTGA(output);
}
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
// TMP TMP
static void viewportToScissor(const CViewport &vp, CScissor &scissor)
{
scissor.X = vp.getX();
scissor.Y = vp.getY();
scissor.Width = vp.getWidth();
scissor.Height = vp.getHeight();
}
// TMP TMP
void tempDumpColPolys()
{
CPackedWorld *pw = R2::getEditor().getIslandCollision().getPackedIsland();
if (pw)
{
static CMaterial material;
static CMaterial wiredMaterial;
static CMaterial texturedMaterial;
static CVertexBuffer vb;
static bool initDone = false;
if (!initDone)
{
vb.setVertexFormat(CVertexBuffer::PositionFlag);
vb.setPreferredMemory(CVertexBuffer::AGPVolatile, false);
material.initUnlit();
material.setDoubleSided(true);
material.setZFunc(CMaterial::lessequal);
wiredMaterial.initUnlit();
wiredMaterial.setDoubleSided(true);
wiredMaterial.setZFunc(CMaterial::lessequal);
wiredMaterial.setColor(CRGBA(255, 255, 255, 250));
wiredMaterial.texEnvOpAlpha(0, CMaterial::Replace);
wiredMaterial.texEnvArg0Alpha(0, CMaterial::Diffuse, CMaterial::SrcAlpha);
wiredMaterial.setBlend(true);
wiredMaterial.setBlendFunc(CMaterial::srcalpha, CMaterial::invsrcalpha);
texturedMaterial.initUnlit();
texturedMaterial.setDoubleSided(true);
texturedMaterial.setZFunc(CMaterial::lessequal);
initDone = true;
}
// just add a projected texture
R2::getEditor().getIslandCollision().loadEntryPoints();
R2::CScenarioEntryPoints &sep = R2::CScenarioEntryPoints::getInstance();
CVectorD playerPos = UserEntity->pos();
R2::CScenarioEntryPoints::CCompleteIsland *island = sep.getCompleteIslandFromCoords(CVector2f((float) playerPos.x, (float) playerPos.y));
static CSString currIsland;
if (island && island->Island != currIsland)
{
currIsland = island->Island;
CTextureFile *newTex = new CTextureFile(currIsland + "_sp.tga");
newTex->setWrapS(ITexture::Clamp);
newTex->setWrapT(ITexture::Clamp);
texturedMaterial.setTexture(0, newTex);
texturedMaterial.texEnvOpRGB(0, CMaterial::Replace);
texturedMaterial.texEnvArg0RGB(0, CMaterial::Texture, CMaterial::SrcColor);
texturedMaterial.setTexCoordGen(0, true);
texturedMaterial.setTexCoordGenMode(0, CMaterial::TexCoordGenObjectSpace);
CMatrix mat;
CVector scale((float) (island->XMax - island->XMin),
(float) (island->YMax - island->YMin), 0.f);
scale.x = 1.f / favoid0(scale.x);
scale.y = 1.f / favoid0(scale.y);
scale.z = 0.f;
mat.setScale(scale);
mat.setPos(CVector(- island->XMin * scale.x, - island->YMin * scale.y, 0.f));
//
CMatrix uvScaleMat;
//
uint texWidth = (uint) (island->XMax - island->XMin);
uint texHeight = (uint) (island->YMax - island->YMin);
float UScale = (float) texWidth / raiseToNextPowerOf2(texWidth);
float VScale = (float) texHeight / raiseToNextPowerOf2(texHeight);
//
uvScaleMat.setScale(CVector(UScale, - VScale, 0.f));
uvScaleMat.setPos(CVector(0.f, VScale, 0.f));
//
texturedMaterial.enableUserTexMat(0, true);
texturedMaterial.setUserTexMat(0, uvScaleMat * mat);
}
const CFrustum &frust = MainCam.getFrustum();
//
IDriver *driver = ((CDriverUser *) Driver)->getDriver();
driver->enableFog(true);
const CRGBA clearColor = CRGBA(0, 0, 127, 0);
driver->setupFog(frust.Far * 0.8f, frust.Far, clearColor);
CViewport vp;
vp.init(0.f, 0.f, 1.f, 1.f);
driver->setupViewport(vp);
CScissor scissor;
viewportToScissor(vp, scissor);
driver->setupScissor(scissor);
//
driver->setFrustum(frust.Left, frust.Right, frust.Bottom, frust.Top, frust.Near, frust.Far, frust.Perspective);
driver->setupViewMatrix(MainCam.getMatrix().inverted());
driver->setupModelMatrix(CMatrix::Identity);
//
//
const CVector localFrustCorners[8] =
{
CVector(frust.Left, frust.Near, frust.Top),
CVector(frust.Right, frust.Near, frust.Top),
CVector(frust.Right, frust.Near, frust.Bottom),
CVector(frust.Left, frust.Near, frust.Bottom),
CVector(frust.Left * frust.Far / frust.Near, frust.Far, frust.Top * frust.Far / frust.Near),
CVector(frust.Right * frust.Far / frust.Near, frust.Far, frust.Top * frust.Far / frust.Near),
CVector(frust.Right * frust.Far / frust.Near, frust.Far, frust.Bottom * frust.Far / frust.Near),
CVector(frust.Left * frust.Far / frust.Near, frust.Far, frust.Bottom * frust.Far / frust.Near)
};
// roughly compute covered zones
//
/*
sint frustZoneMinX = INT_MAX;
sint frustZoneMaxX = INT_MIN;
sint frustZoneMinY = INT_MAX;
sint frustZoneMaxY = INT_MIN;
for(uint k = 0; k < sizeofarray(localFrustCorners); ++k)
{
CVector corner = camMat * localFrustCorners[k];
sint zoneX = (sint) (corner.x / 160.f) - zoneMinX;
sint zoneY = (sint) floorf(corner.y / 160.f) - zoneMinY;
frustZoneMinX = std::min(frustZoneMinX, zoneX);
frustZoneMinY = std::min(frustZoneMinY, zoneY);
frustZoneMaxX = std::max(frustZoneMaxX, zoneX);
frustZoneMaxY = std::max(frustZoneMaxY, zoneY);
}
*/
const uint TRI_BATCH_SIZE = 10000; // batch size for rendering
static std::vector<TPackedZoneBaseSPtr> zones;
zones.clear();
pw->getZones(zones);
for(uint k = 0; k < zones.size(); ++k)
{
zones[k]->render(vb, *driver, texturedMaterial, wiredMaterial, MainCam.getMatrix(), TRI_BATCH_SIZE, localFrustCorners);
}
}
}
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
// ********************************************************************
/* end of file */

View file

@ -0,0 +1,30 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
#ifndef CL_MAIN_LOOP_TEMP_H
#define CL_MAIN_LOOP_TEMP_H
#include <nel/misc/types_nl.h>
// TMP TMP
void tempDumpValidPolys();
// TMP TMP
void tempDumpColPolys();
#endif // CL_MAIN_LOOP_TEMP_H
/* end of file */

View file

@ -0,0 +1,341 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
#include <nel/misc/types_nl.h>
#include "main_loop_utilities.h"
#include <nel/3d/u_driver.h>
#include <nel/3d/u_cloud_scape.h>
#include "game_share/scenario_entry_points.h"
#include "client_cfg.h"
#include "misc.h"
#include "global.h"
#include "world_database_manager.h"
#include "continent_manager.h"
#include "user_entity.h"
#include "view.h"
#include "ig_client.h"
#include "entities.h"
#include "input.h"
#include "sound_manager.h"
#include "camera.h"
using namespace NLMISC;
using namespace NL3D;
//---------------------------------------------------
// Compare ClientCfg and LastClientCfg to know what we must update
//---------------------------------------------------
void updateFromClientCfg()
{
CClientConfig::setValues();
ClientCfg.IsInvalidated = false;
// GRAPHICS - GENERAL
//---------------------------------------------------
if ((ClientCfg.Windowed != LastClientCfg.Windowed) ||
(ClientCfg.Width != LastClientCfg.Width) ||
(ClientCfg.Height != LastClientCfg.Height) ||
(ClientCfg.Depth != LastClientCfg.Depth) ||
(ClientCfg.Frequency != LastClientCfg.Frequency))
{
setVideoMode(UDriver::CMode(ClientCfg.Width, ClientCfg.Height, (uint8)ClientCfg.Depth,
ClientCfg.Windowed, ClientCfg.Frequency));
}
if (ClientCfg.DivideTextureSizeBy2 != LastClientCfg.DivideTextureSizeBy2)
{
if (ClientCfg.DivideTextureSizeBy2)
Driver->forceTextureResize(2);
else
Driver->forceTextureResize(1);
}
//---------------------------------------------------
if (ClientCfg.WaitVBL != LastClientCfg.WaitVBL)
{
if(ClientCfg.WaitVBL)
Driver->setSwapVBLInterval(1);
else
Driver->setSwapVBLInterval(0);
}
// GRAPHICS - LANDSCAPE
//---------------------------------------------------
if (ClientCfg.LandscapeThreshold != LastClientCfg.LandscapeThreshold)
{
if (Landscape) Landscape->setThreshold(ClientCfg.getActualLandscapeThreshold());
}
//---------------------------------------------------
if (ClientCfg.LandscapeTileNear != LastClientCfg.LandscapeTileNear)
{
if (Landscape) Landscape->setTileNear(ClientCfg.LandscapeTileNear);
}
//---------------------------------------------------
if (Landscape)
{
if (ClientCfg.Vision != LastClientCfg.Vision)
{
if (!ClientCfg.Light)
{
// Not in an indoor ?
if (ContinentMngr.cur() && !ContinentMngr.cur()->Indoor)
{
// Refresh All Zone in streaming according to the refine position
std::vector<string> zonesAdded;
std::vector<string> zonesRemoved;
const R2::CScenarioEntryPoints::CCompleteIsland *ci = R2::CScenarioEntryPoints::getInstance().getCompleteIslandFromCoords(CVector2f((float) UserEntity->pos().x, (float) UserEntity->pos().y));
Landscape->refreshAllZonesAround(View.refinePos(), ClientCfg.Vision + ExtraZoneLoadingVision, zonesAdded, zonesRemoved, ProgressBar, ci ? &(ci->ZoneIDs) : NULL);
LandscapeIGManager.unloadArrayZoneIG(zonesRemoved);
LandscapeIGManager.loadArrayZoneIG(zonesAdded);
}
}
}
}
//---------------------------------------------------
if (ClientCfg.Vision != LastClientCfg.Vision || ClientCfg.FoV!=LastClientCfg.FoV ||
ClientCfg.Windowed != LastClientCfg.Windowed || ClientCfg.ScreenAspectRatio != LastClientCfg.ScreenAspectRatio )
{
updateCameraPerspective();
}
//---------------------------------------------------
if (Landscape)
{
if (ClientCfg.MicroVeget != LastClientCfg.MicroVeget)
{
if(ClientCfg.MicroVeget)
{
// if configured, enable the vegetable and load the texture.
Landscape->enableVegetable(true);
// Default setup. TODO later by gameDev.
Landscape->setVegetableWind(CVector(0.5, 0.5, 0).normed(), 0.5, 1, 0);
// Default setup. should work well for night/day transition in 30 minutes.
// Because all vegetables will be updated every 20 seconds => 90 steps.
Landscape->setVegetableUpdateLightingFrequency(1/20.f);
// Density (percentage to ratio)
Landscape->setVegetableDensity(ClientCfg.MicroVegetDensity/100.f);
}
else
{
Landscape->enableVegetable(false);
}
}
}
//---------------------------------------------------
if (ClientCfg.MicroVegetDensity != LastClientCfg.MicroVegetDensity)
{
// Density (percentage to ratio)
if (Landscape) Landscape->setVegetableDensity(ClientCfg.MicroVegetDensity/100.f);
}
// GRAPHICS - SPECIAL EFFECTS
//---------------------------------------------------
if (ClientCfg.FxNbMaxPoly != LastClientCfg.FxNbMaxPoly)
{
if (Scene->getGroupLoadMaxPolygon("Fx") != ClientCfg.FxNbMaxPoly)
Scene->setGroupLoadMaxPolygon("Fx", ClientCfg.FxNbMaxPoly);
}
//---------------------------------------------------
if (ClientCfg.Cloud != LastClientCfg.Cloud)
{
if (ClientCfg.Cloud)
{
InitCloudScape = true;
CloudScape = Scene->createCloudScape();
}
else
{
if (CloudScape != NULL)
Scene->deleteCloudScape(CloudScape);
CloudScape = NULL;
}
}
//---------------------------------------------------
if (ClientCfg.CloudQuality != LastClientCfg.CloudQuality)
{
if (CloudScape != NULL)
CloudScape->setQuality(ClientCfg.CloudQuality);
}
//---------------------------------------------------
if (ClientCfg.CloudUpdate != LastClientCfg.CloudUpdate)
{
if (CloudScape != NULL)
CloudScape->setNbCloudToUpdateIn80ms(ClientCfg.CloudUpdate);
}
//---------------------------------------------------
if (ClientCfg.Shadows != LastClientCfg.Shadows)
{
// Enable/Disable Receive on Landscape
if(Landscape)
{
Landscape->enableReceiveShadowMap(ClientCfg.Shadows);
}
// Enable/Disable Cast for all entities
for(uint i=0;i<EntitiesMngr.entities().size();i++)
{
CEntityCL *ent= EntitiesMngr.entities()[i];
if(ent)
ent->updateCastShadowMap();
}
}
// GRAPHICS - CHARACTERS
//---------------------------------------------------
if (ClientCfg.SkinNbMaxPoly != LastClientCfg.SkinNbMaxPoly)
{
if (Scene->getGroupLoadMaxPolygon("Skin") != ClientCfg.SkinNbMaxPoly)
Scene->setGroupLoadMaxPolygon("Skin", ClientCfg.SkinNbMaxPoly);
}
//---------------------------------------------------
if (ClientCfg.NbMaxSkeletonNotCLod != LastClientCfg.NbMaxSkeletonNotCLod )
{
Scene->setMaxSkeletonsInNotCLodForm(ClientCfg.NbMaxSkeletonNotCLod);
}
//---------------------------------------------------
if (ClientCfg.CharacterFarClip != LastClientCfg.CharacterFarClip)
{
// Nothing to do
}
//---------------------------------------------------
if (ClientCfg.HDEntityTexture != LastClientCfg.HDEntityTexture)
{
// Don't reload Texture, will be done at next Game Start
}
// INTERFACE works
// INPUTS
//---------------------------------------------------
if (ClientCfg.CursorSpeed != LastClientCfg.CursorSpeed)
SetMouseSpeed (ClientCfg.CursorSpeed);
if (ClientCfg.CursorAcceleration != LastClientCfg.CursorAcceleration)
SetMouseAcceleration (ClientCfg.CursorAcceleration);
if (ClientCfg.HardwareCursor != LastClientCfg.HardwareCursor)
{
if (ClientCfg.HardwareCursor != IsMouseCursorHardware())
{
InitMouseWithCursor (ClientCfg.HardwareCursor);
}
}
// SOUND
//---------------------------------------------------
bool mustReloadSoundMngrContinent= false;
// disable/enable sound?
if (ClientCfg.SoundOn != LastClientCfg.SoundOn)
{
if (SoundMngr && !ClientCfg.SoundOn)
{
nlwarning("Deleting sound manager...");
delete SoundMngr;
SoundMngr = NULL;
}
else if (SoundMngr == NULL && ClientCfg.SoundOn)
{
nlwarning("Creating sound manager...");
SoundMngr = new CSoundManager();
try
{
SoundMngr->init(NULL);
}
catch(const Exception &e)
{
nlwarning("init : Error when creating 'SoundMngr' : %s", e.what());
SoundMngr = 0;
}
// re-init with good SFX/Music Volume
if(SoundMngr)
{
SoundMngr->setSFXVolume(ClientCfg.SoundSFXVolume);
SoundMngr->setGameMusicVolume(ClientCfg.SoundGameMusicVolume);
}
}
else
{
nlwarning("Sound config error !");
}
mustReloadSoundMngrContinent= true;
}
// change EAX?
if ( SoundMngr && LastClientCfg.SoundOn &&
(ClientCfg.UseEax != LastClientCfg.UseEax) )
{
SoundMngr->reset();
mustReloadSoundMngrContinent= true;
}
// change SoundForceSoftwareBuffer?
if ( SoundMngr && LastClientCfg.SoundOn &&
(ClientCfg.SoundForceSoftwareBuffer != LastClientCfg.SoundForceSoftwareBuffer) )
{
SoundMngr->reset();
mustReloadSoundMngrContinent= true;
}
// change MaxTrack? don't reset
if ( SoundMngr && LastClientCfg.SoundOn &&
(ClientCfg.MaxTrack != LastClientCfg.MaxTrack))
{
SoundMngr->getMixer()->changeMaxTrack(ClientCfg.MaxTrack);
}
// change SoundFX Volume? don't reset
if (SoundMngr && ClientCfg.SoundSFXVolume != LastClientCfg.SoundSFXVolume)
{
SoundMngr->setSFXVolume(ClientCfg.SoundSFXVolume);
}
// change Game Music Volume? don't reset
if (SoundMngr && ClientCfg.SoundGameMusicVolume != LastClientCfg.SoundGameMusicVolume)
{
SoundMngr->setGameMusicVolume(ClientCfg.SoundGameMusicVolume);
}
// reload only if active and reseted
if (mustReloadSoundMngrContinent && SoundMngr && ContinentMngr.cur() && !ContinentMngr.cur()->Indoor && UserEntity)
{
SoundMngr->loadContinent(ContinentMngr.getCurrentContinentSelectName(), UserEntity->pos());
}
// Ok backup the new clientcfg
LastClientCfg = ClientCfg;
}
/* end of file */

View file

@ -0,0 +1,32 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
#ifndef CL_MAIN_LOOP_UTILITIES_H
#define CL_MAIN_LOOP_UTILITIES_H
#include <nel/misc/types_nl.h>
// Update Utilities (configuration etc)
// Only put utility update functions here that are used in the main loop.
// This is mainly for system configuration related functions
// such as config file changes.
/// Compare ClientCfg and LastClientCfg to know what we must update
void updateFromClientCfg();
#endif // CL_MAIN_LOOP_UTILITIES_H
/* end of file */

View file

@ -0,0 +1,74 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
#include <nel/misc/types_nl.h>
#include "ping.h"
#include "interface_v3/interface_manager.h"
#include "time_client.h"
using namespace NLMISC;
using namespace NLGUI;
void CPing::init()
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
if(pIM)
{
CCDBNodeLeaf *pNodeLeaf = CDBManager::getInstance()->getDbProp("SERVER:DEBUG_INFO:Ping", false);
if(pNodeLeaf)
{
ICDBNode::CTextId textId;
pNodeLeaf->addObserver(this, textId);
// nlwarning("CPing: cannot add the observer");
}
else
nlwarning("CPing: 'SERVER:DEBUG_INFO:Ping' does not exist.");
}
}
void CPing::release()
{
CInterfaceManager *pIM = CInterfaceManager::getInstance();
if(pIM)
{
CCDBNodeLeaf *pNodeLeaf = CDBManager::getInstance()->getDbProp("SERVER:DEBUG_INFO:Ping", false);
if(pNodeLeaf)
{
ICDBNode::CTextId textId;
pNodeLeaf->removeObserver(this, textId);
}
else
nlwarning("CPing: 'SERVER:DEBUG_INFO:Ping' does not exist.");
}
}
void CPing::update(NLMISC::ICDBNode* node)
{
CCDBNodeLeaf *leaf = safe_cast<CCDBNodeLeaf *>(node);
uint32 before = (uint32)leaf->getValue32();
uint32 current = (uint32)(0xFFFFFFFF & ryzomGetLocalTime());
if(before > current)
{
//nlwarning("DB PING Pb before '%u' after '%u'.", before, current);
if(ClientCfg.Check)
nlstop;
}
_Ping = current - before;
_RdyToPing = true;
}
/* end of file */

View file

@ -0,0 +1,62 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
#ifndef CL_PING_H
#define CL_PING_H
#include <nel/misc/types_nl.h>
#include <nel/misc/cdb.h>
///////////
// CLASS //
///////////
/**
* Class to manage the ping computed with the database.
* \author Guillaume PUZIN
* \author Nevrax France
* \date 2003
*/
class CPing : public NLMISC::ICDBNode::IPropertyObserver
{
private:
uint32 _Ping;
bool _RdyToPing;
public:
// Constructor.
CPing() {_Ping = 0; _RdyToPing = true;}
// Destructor.
~CPing() {;}
// Add an observer on the database for the ping.
void init();
// Release the observer on the database for the ping.
void release();
// Method called when the ping message is back.
virtual void update(NLMISC::ICDBNode* node);
// return the ping in ms.
uint32 getValue() {return _Ping;}
void rdyToPing(bool rdy) {_RdyToPing = rdy;}
bool rdyToPing() const {return _RdyToPing;}
};
#endif // CL_PING_H
/* end of file */

Some files were not shown because too many files have changed in this diff Show more