Coverage Report

Created: 2025-07-11 06:33

/src/ogre/OgreMain/include/OgreInstanceBatchVTF.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
    (Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
15
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
18
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
THE SOFTWARE.
26
-----------------------------------------------------------------------------
27
*/
28
#ifndef __BaseInstanceBatchVTF_H__
29
#define __BaseInstanceBatchVTF_H__
30
31
#include "OgreInstanceBatch.h"
32
#include "OgreTexture.h"
33
#include "OgreHeaderPrefix.h"
34
35
namespace Ogre
36
{
37
    /** \addtogroup Core
38
    *  @{
39
    */
40
    /** \addtogroup Scene
41
    *  @{
42
    */
43
44
    /** Instancing implementation using vertex texture through Vertex Texture Fetch (VTF)
45
        This implementation has the following advantages:
46
          - Supports huge amount of instances per batch
47
          - Supports skinning even with huge ammounts of instances per batch
48
          - Doesn't need shader constants registers.
49
          - Best suited for skinned entities
50
51
        But beware the disadvantages:
52
          - VTF is only fast on modern GPUs (ATI Radeon HD 2000+, GeForce 8+ series onwards)
53
          - On GeForce 6/7 series VTF is too slow
54
          - VTF isn't (controversely) supported on old ATI X1800 hardware
55
          - Only one bone weight per vertex is supported
56
          - GPUs with low memory bandwidth (i.e. laptops and integrated GPUs)
57
          may perform even worse than no instancing
58
59
        Whether this performs great or bad depends on the hardware. It improved up to 4x performance on
60
        a Intel Core 2 Quad Core X9650 GeForce 8600 GTS, and in an Intel Core 2 Duo P7350 ATI
61
        Mobility Radeon HD 4650, but went 0.75x slower on an AthlonX2 5000+ integrated nForce 6150 SE
62
        Each BaseInstanceBatchVTF has it's own texture, which occupies memory in VRAM.
63
        Approx VRAM usage can be computed by doing 12 bytes * 3 * numInstances * numBones
64
        Use flag IM_VTFBESTFIT to avoid wasting VRAM (but may reduce amount of instances per batch).
65
66
        The material requires at least a texture unit stage named @c InstancingVTF
67
68
     */
69
    class _OgreExport BaseInstanceBatchVTF : public InstanceBatch
70
    {
71
    protected:
72
        typedef std::vector<uint8> HWBoneIdxVec;
73
        typedef std::vector<float> HWBoneWgtVec;
74
        typedef std::vector<Matrix4> Matrix4Vec;
75
76
        size_t                  mMatricesPerInstance; //number of bone matrices per instance
77
        size_t                  mNumWorldMatrices;  //Num bones * num instances
78
        TexturePtr              mMatrixTexture; //The VTF
79
80
        //Used when all matrices from each instance must be in the same row (i.e. HW Instancing).
81
        //A few pixels are wasted, but resizing the texture puts the danger of not sampling the
82
        //right pixel... (in theory it should work, but in practice doesn't)
83
        size_t                  mWidthFloatsPadding;
84
        size_t                  mMaxFloatsPerLine;
85
86
        size_t                  mRowLength;
87
        size_t                  mWeightCount;
88
        //Temporary array used to store 3x4 matrices before they are converted to dual quaternions
89
        Matrix3x4f*             mTempTransformsArray3x4;
90
91
        // The state of the usage of bone matrix lookup
92
        bool mUseBoneMatrixLookup;
93
        size_t mMaxLookupTableInstances;
94
95
        bool mUseBoneDualQuaternions;
96
        bool mForceOneWeight;
97
        bool mUseOneWeight;
98
99
        /** Clones the base material so it can have it's own vertex texture, and also
100
            clones it's shadow caster materials, if it has any
101
        */
102
        void cloneMaterial( const MaterialPtr &material );
103
104
        /** Retrieves bone data from the original sub mesh and puts it into an appropriate buffer,
105
            later to be read when creating the vertex semantics.
106
            Assumes outBoneIdx has enough space (base submesh vertex count)
107
        */
108
        void retrieveBoneIdx( VertexData *baseVertexData, HWBoneIdxVec &outBoneIdx );
109
110
        /** @see retrieveBoneIdx()
111
            Assumes outBoneIdx has enough space (twice the base submesh vertex count, one for each weight)
112
            Assumes outBoneWgt has enough space (twice the base submesh vertex count, one for each weight)
113
        */
114
        void retrieveBoneIdxWithWeights(VertexData *baseVertexData, HWBoneIdxVec &outBoneIdx, HWBoneWgtVec &outBoneWgt);
115
116
        /** Setups the material to use a vertex texture */
117
        void setupMaterialToUseVTF( TextureType textureType, MaterialPtr &material ) const;
118
119
        /** Creates the vertex texture */
120
        void createVertexTexture( const SubMesh* baseSubMesh );
121
122
        /** Creates 2 TEXCOORD semantics that will be used to sample the vertex texture */
123
        virtual void createVertexSemantics( VertexData *thisVertexData, VertexData *baseVertexData,
124
                                    const HWBoneIdxVec &hwBoneIdx, const HWBoneWgtVec &hwBoneWgt) = 0;
125
126
        size_t convert3x4MatricesToDualQuaternions(Matrix3x4f* matrices, size_t numOfMatrices, float* outDualQuaternions);
127
                                    
128
        /** Keeps filling the VTF with world matrix data */
129
        void updateVertexTexture(void);
130
131
        /** Affects VTF texture's width dimension */
132
        virtual bool matricesTogetherPerRow() const = 0;
133
134
        /** update the lookup numbers for entities with shared transforms */
135
        virtual void updateSharedLookupIndexes();
136
137
        /** @see InstanceBatch::generateInstancedEntity() */
138
        InstancedEntity* generateInstancedEntity(size_t num) override;
139
140
    public:
141
        BaseInstanceBatchVTF( InstanceManager *creator, MeshPtr &meshReference, const MaterialPtr &material,
142
                            size_t instancesPerBatch, const Mesh::IndexMap *indexToBoneMap,
143
                            const String &batchName);
144
        virtual ~BaseInstanceBatchVTF();
145
146
        /** @see InstanceBatch::buildFrom */
147
        void buildFrom( const SubMesh *baseSubMesh, const RenderOperation &renderOperation ) override;
148
149
        //Renderable overloads
150
        void getWorldTransforms( Matrix4* xform ) const override;
151
152
        /** Overloaded to be able to updated the vertex texture */
153
        void _updateRenderQueue(RenderQueue* queue) override;
154
155
        /** Sets the state of the usage of bone matrix lookup
156
        
157
        Under default condition each instance entity is assigned a specific area in the vertex 
158
        texture for bone matrix data. When turned on the amount of area in the vertex texture 
159
        assigned for bone matrix data will be relative to the amount of unique animation states.
160
        Instanced entities sharing the same animation state will share the same area in the matrix.
161
        The specific position of each entity is placed in the vertex data and added in a second phase
162
        in the shader.
163
164
        Note this feature only works in VTF_HW for now.
165
        This value needs to be set before adding any instanced entities
166
        */
167
0
        void setBoneMatrixLookup(bool enable, size_t maxLookupTableInstances) { assert(mInstancedEntities.empty()); 
168
0
            mUseBoneMatrixLookup = enable; mMaxLookupTableInstances = maxLookupTableInstances; }
169
170
        /** Tells whether to use bone matrix lookup
171
        @see setBoneMatrixLookup()
172
        */
173
0
        bool useBoneMatrixLookup() const { return mUseBoneMatrixLookup; }
174
175
0
        void setBoneDualQuaternions(bool enable) { assert(mInstancedEntities.empty());
176
0
            mUseBoneDualQuaternions = enable; mRowLength = (mUseBoneDualQuaternions ? 2 : 3); }
177
178
0
        bool useBoneDualQuaternions() const { return mUseBoneDualQuaternions; }
179
180
0
        void setForceOneWeight(bool enable) {  assert(mInstancedEntities.empty());
181
0
            mForceOneWeight = enable; }
182
183
0
        bool forceOneWeight() const { return mForceOneWeight; }
184
185
0
        void setUseOneWeight(bool enable) {  assert(mInstancedEntities.empty());
186
0
            mUseOneWeight = enable; }
187
188
0
        bool useOneWeight() const { return mUseOneWeight; }
189
190
        /** @see InstanceBatch::useBoneWorldMatrices()  */
191
0
        bool useBoneWorldMatrices() const override { return !mUseBoneMatrixLookup; }
192
193
        /** @return the maximum amount of shared transform entities when using lookup table*/
194
0
        virtual size_t getMaxLookupTableInstances() const { return mMaxLookupTableInstances; }
195
        
196
    };
197
198
    class _OgreExport InstanceBatchVTF : public BaseInstanceBatchVTF
199
    {
200
        
201
        void setupVertices( const SubMesh* baseSubMesh ) override;
202
        void setupIndices( const SubMesh* baseSubMesh ) override;
203
204
        /** Creates 2 TEXCOORD semantics that will be used to sample the vertex texture */
205
        void createVertexSemantics( VertexData *thisVertexData, VertexData *baseVertexData,
206
            const HWBoneIdxVec &hwBoneIdx, const HWBoneWgtVec &hwBoneWgt ) override;
207
208
0
        bool matricesTogetherPerRow() const override { return false; }
209
    public:
210
        InstanceBatchVTF( InstanceManager *creator, MeshPtr &meshReference, const MaterialPtr &material,
211
                            size_t instancesPerBatch, const Mesh::IndexMap *indexToBoneMap,
212
                            const String &batchName);
213
        virtual ~InstanceBatchVTF();
214
215
        /** @see InstanceBatch::calculateMaxNumInstances */
216
        size_t calculateMaxNumInstances( const SubMesh *baseSubMesh, uint16 flags ) const override;
217
    };
218
}
219
220
#include "OgreHeaderSuffix.h"
221
222
#endif