Ticket #3073: Instancing_v1b.patch

File Instancing_v1b.patch, 10.8 KB (added by wraitii, 9 years ago)

Simple instancing patch. This will actually instance objects the game wants to instance. Requires GL_ARB_draw_instanced. Naive and probably buggy but it works with onematerial.patch

  • binaries/data/mods/public/shaders/glsl/model_common.vs

     
    11#version 120
     2#extension GL_ARB_draw_instanced : enable
    23
    34uniform mat4 transform;
    45uniform vec3 cameraPos;
     
    1112#endif
    1213uniform vec2 losTransform;
    1314uniform mat4 shadowTransform;
    14 uniform mat4 instancingTransform;
     15uniform mat4 instancingTransforms[250];
    1516
    1617#if USE_SHADOW_SAMPLER && USE_SHADOW_PCF
    1718  uniform vec4 shadowScale;
     
    7475
    7576void main()
    7677{
     78  mat4 instancingTransform = instancingTransforms[gl_InstanceIDARB];//mat4(a_instancingTransform0, a_instancingTransform1, a_instancingTransform2, a_instancingTransform3);
     79
    7780  #if USE_GPU_SKINNING
    7881    vec3 p = vec3(0.0);
    7982    vec3 n = vec3(0.0);
  • source/graphics/ShaderProgram.cpp

     
    484484        pglUseProgramObjectARB(m_Program);
    485485
    486486        for (std::map<CStrIntern, int>::iterator it = m_VertexAttribs.begin(); it != m_VertexAttribs.end(); ++it)
     487        {
    487488            pglEnableVertexAttribArrayARB(it->second);
     489
     490            if (it->first == str_a_instancingTransform0
     491                    || it->first == str_a_instancingTransform1
     492                    || it->first == str_a_instancingTransform2
     493                    || it->first == str_a_instancingTransform3
     494            )
     495            {
     496                pglVertexAttribDivisorARB(it->second, 1);
    488497    }
     498        }
     499    }
    489500
    490501    virtual void Unbind()
    491502    {
     
    492503        pglUseProgramObjectARB(0);
    493504
    494505        for (std::map<CStrIntern, int>::iterator it = m_VertexAttribs.begin(); it != m_VertexAttribs.end(); ++it)
     506        {
    495507            pglDisableVertexAttribArrayARB(it->second);
     508            pglVertexAttribDivisorARB(it->second, 0);
     509        }
    496510
    497511        // TODO: should unbind textures, probably
    498512    }
  • source/lib/external_libraries/glext_funcs.h

     
    383383FUNC(void, glDeletePerfQueryINTEL, (GLuint id))
    384384FUNC(void, glGetPerfQueryDataINTEL, (GLuint id, GLenum requestType, GLuint maxLength, char *buffer, GLuint *length))
    385385
     386// GL_ARB_draw_instanced
     387FUNC(void, glDrawArraysInstancedARB, (GLenum mode, GLint first, GLsizei count, GLsizei primcount))
     388FUNC(void, glDrawElementsInstancedARB, (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount))
     389
     390// GL_ARB_instanced_arrays
     391FUNC(void, glVertexAttribDivisorARB, (GLuint index, GLuint divisor))
     392
    386393#endif  // #if CONFIG_GLES2
    387394
    388395
  • source/ps/CStrInternStatic.h

     
    7373X(a_splashPosition)
    7474X(a_tangent)
    7575X(a_waterInfo)
     76X(a_instancingTransform0)
     77X(a_instancingTransform1)
     78X(a_instancingTransform2)
     79X(a_instancingTransform3)
    7680X(ambient)
    7781X(baseTex)
    7882X(blendTex)
     
    99103X(hdr)
    100104X(height)
    101105X(instancingTransform)
     106X2(instancingTransforms, "instancingTransforms[0]")
    102107X(losMap)
    103108X(losMatrix)
    104109X(losTex)
  • source/renderer/ModelVertexRenderer.h

     
    154154     * succeed.
    155155     */
    156156    virtual void RenderModel(const CShaderProgramPtr& shader, int streamflags, CModel* model, CModelRData* data) = 0;
     157
     158    virtual void RenderModelInstanced(const CShaderProgramPtr& shader, int streamflags, CModel* model, size_t count) { };
     159   
     160    virtual bool IsInstanced() const = 0;
     161
    157162};
    158163
    159164
  • source/renderer/VertexArray.h

     
    157157    };
    158158   
    159159public:
    160     VertexArray(GLenum usage, GLenum target = GL_ARRAY_BUFFER);
     160    VertexArray(GLenum usage = GL_DYNAMIC_DRAW, GLenum target = GL_ARRAY_BUFFER);
    161161    ~VertexArray();
    162162   
    163163    // Set the number of vertices stored in the array
  • source/renderer/InstancingModelRenderer.cpp

     
    389389    g_Renderer.m_Stats.m_ModelTris += numFaces;
    390390
    391391}
     392
     393void InstancingModelRenderer::RenderModelInstanced(const CShaderProgramPtr& shader, int UNUSED(streamflags), CModel* model, size_t count)
     394{
     395    CModelDefPtr mdldef = model->GetModelDef();
     396
     397    // render the lot
     398    size_t numFaces = mdldef->GetNumFaces();
     399    if (!g_Renderer.m_SkipSubmit)
     400    {
     401        // Draw with DrawRangeElements where available, since it might be more efficient
     402        pglDrawElementsInstancedARB(GL_TRIANGLES, (GLsizei)numFaces*3, GL_UNSIGNED_SHORT, m->imodeldefIndexBase, count);
     403//      pglDrawRangeElementsEXT(GL_TRIANGLES, 0, (GLuint)m->imodeldef->m_Array.GetNumVertices()-1,
     404//              (GLsizei)numFaces*3, GL_UNSIGNED_SHORT, m->imodeldefIndexBase);
     405    }
     406
     407    // bump stats
     408    g_Renderer.m_Stats.m_DrawCalls++;
     409    g_Renderer.m_Stats.m_ModelTris += numFaces * count;
     410
     411}
  • source/renderer/HWLightingModelRenderer.h

     
    4747    void PrepareModelDef(const CShaderProgramPtr& shader, int streamflags, const CModelDef& def);
    4848    void RenderModel(const CShaderProgramPtr& shader, int streamflags, CModel* model, CModelRData* data);
    4949
     50    bool IsInstanced() const { return false; };
     51
    5052protected:
    5153    ShaderModelRendererInternals* m;
    5254};
  • source/renderer/ModelRenderer.cpp

     
    215215
    216216    /// List of submitted models for rendering in this frame
    217217    std::vector<CModel*> submissions[CRenderer::CULL_MAX];
     218
     219#define NUM_INSTANCING_ARRAYS 256
     220    VertexArray instancingArray[NUM_INSTANCING_ARRAYS];
     221    VertexArray::Attribute instancingTransform[NUM_INSTANCING_ARRAYS][4];
     222    size_t currentInstancingArray;
    218223};
    219224
    220225
     
    223228{
    224229    m = new ShaderModelRendererInternals(this);
    225230    m->vertexRenderer = vertexrenderer;
     231
     232    for (size_t j = 0; j < NUM_INSTANCING_ARRAYS; ++j)
     233    {
     234        for (size_t i = 0; i < 4; ++i)
     235        {
     236            m->instancingTransform[j][i].type = GL_FLOAT;
     237            m->instancingTransform[j][i].elems = 4;
     238            m->instancingArray[j].AddAttribute(&m->instancingTransform[j][i]);
     239        }
     240
     241        m->instancingArray[j].SetNumVertices(64);
     242        m->instancingArray[j].Layout();
     243    }
     244
     245    m->currentInstancingArray = 0;
    226246}
    227247
    228248ShaderModelRenderer::~ShaderModelRenderer()
     
    363383    }
    364384};
    365385
     386bool hasChanged(CModel* lastModel, CModel* newModel)
     387{
     388    if (lastModel->GetModelDef().get() != newModel->GetModelDef().get())
     389        return true;
     390    return false;
     391}
     392
    366393void ShaderModelRenderer::Render(const RenderModifierPtr& modifier, const CShaderDefines& context, int cullGroup, int flags)
    367394{
    368395    if (m->submissions[cullGroup].empty())
     
    618645        typedef ProxyAllocator<CStrIntern, Allocators::DynamicArena> BindingNamesListAllocator;
    619646        std::vector<CStrIntern, BindingNamesListAllocator> texBindingNames((BindingNamesListAllocator(arena)));
    620647        texBindingNames.reserve(64);
    621 
     648printf("----\n");
    622649        while (idxTechStart < techBuckets.size())
    623650        {
    624651            CShaderTechniquePtr currentTech = techBuckets[idxTechStart].tech;
     
    655682
    656683                for (size_t idx = idxTechStart; idx < idxTechEnd; ++idx)
    657684                {
     685                    int instances = 0;
     686
     687                    std::vector<CMatrix3D> instancingTransforms;
     688
    658689                    CModel** models = techBuckets[idx].models;
    659690                    size_t numModels = techBuckets[idx].numModels;
     691
     692                    if (numModels == 0)
     693                        continue;
     694
     695                    CModel* newModel = NULL;
     696                   
    660697                    for (size_t i = 0; i < numModels; ++i)
    661698                    {
    662699                        CModel* model = models[i];
    663 
     700                       
    664701                        if (flags && !(model->GetFlags() & flags))
    665702                            continue;
    666 
     703                       
     704                        if (m->vertexRenderer->IsInstanced())
     705                        {
     706                            instances++;
     707                            CMatrix3D transform = model->GetTransform();
     708                            instancingTransforms.push_back(transform);
     709                       
     710                            if (i < numModels-1)
     711                            {
     712                                newModel = models[i+1];
     713                                while (i < numModels-1 && instances < 250 && !hasChanged(model, newModel)) {
     714                                    model = models[++i];
     715                                    instances++;
     716                                    CMatrix3D transform = model->GetTransform();
     717                                    instancingTransforms.push_back(transform);
     718                                    newModel = models[i+1];
     719                                }
     720                            }
     721                        }
     722                       
    667723                        const CMaterial::SamplersVector& samplers = model->GetMaterial().GetSamplers();
    668724                        size_t samplersNum = samplers.size();
    669725                       
     
    730786                        for (size_t q = 0; q < renderQueries.GetSize(); q++)
    731787                        {
    732788                            CShaderRenderQueries::RenderQuery rq = renderQueries.GetItem(q);
    733                             if (rq.first == RQUERY_TIME)
     789                            if (rq.first == RQUERY_TIME && i == 0)
    734790                            {
    735791                                CShaderProgram::Binding binding = shader->GetUniformBinding(rq.second);
    736792                                if (binding.Active())
     
    756812                                shader->BindTexture(str_skyCube, g_Renderer.GetSkyManager()->GetSkyCube());
    757813                            }
    758814                        }
    759 
     815                       
    760816                        modifier->PrepareModel(shader, model);
    761 
     817                       
     818                        if (m->vertexRenderer->IsInstanced())
     819                        {
     820                            shader->Uniform(str_instancingTransforms, instancingTransforms.size(), &instancingTransforms[0]);
     821                            m->vertexRenderer->RenderModelInstanced(shader, streamflags, model, instances);
     822                            instances = 0;
     823                            instancingTransforms.clear();
     824                        }
     825                        else
     826                        {
    762827                        CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
    763828                        ENSURE(rdata->GetKey() == m->vertexRenderer.get());
    764 
     829                           
    765830                        m->vertexRenderer->RenderModel(shader, streamflags, model, rdata);
    766831                    }
    767832                }
     833                }
    768834
    769835                m->vertexRenderer->EndPass(streamflags);
    770836
  • source/renderer/InstancingModelRenderer.h

     
    4646    void EndPass(int streamflags);
    4747    void PrepareModelDef(const CShaderProgramPtr& shader, int streamflags, const CModelDef& def);
    4848    void RenderModel(const CShaderProgramPtr& shader, int streamflags, CModel* model, CModelRData* data);
     49    void RenderModelInstanced(const CShaderProgramPtr& shader, int streamflags, CModel* model, size_t count);
    4950
     51    bool IsInstanced() const { return true; }
     52   
    5053protected:
    5154    InstancingModelRendererInternals* m;
    5255};