diff options
| author | Alexander Gavriliuk <alexandrgproductengine@lindenlab.com> | 2024-08-07 20:56:10 +0200 | 
|---|---|---|
| committer | Guru <alexandrgproductengine@lindenlab.com> | 2024-08-08 13:40:23 +0200 | 
| commit | 17f7b439d617bfdf4c865f1478ade662e86b61d2 (patch) | |
| tree | 87ce6eaf3691e8ce14c98364fc81fa27e3e1eb1f | |
| parent | e20e387d481513e4e7eed570d224da19aa532fb8 (diff) | |
#1922 Make PBR scale and offset crosshair work like Texture crosshair do
| -rw-r--r-- | indra/llrender/llrender.h | 19 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 12 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.h | 9 | ||||
| -rw-r--r-- | indra/newview/llface.cpp | 116 | ||||
| -rw-r--r-- | indra/newview/llface.h | 4 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 159 | ||||
| -rw-r--r-- | indra/newview/pipeline.h | 1 | 
7 files changed, 210 insertions, 110 deletions
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index e6b4118beb..010ab122b6 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -293,15 +293,18 @@ public:      enum eTexIndex : U8      { -        DIFFUSE_MAP           = 0, -        ALTERNATE_DIFFUSE_MAP = 1, -        NORMAL_MAP            = 1, -        SPECULAR_MAP          = 2, -        BASECOLOR_MAP         = 3, +        // Channels for material textures +        DIFFUSE_MAP            = 0, +        ALTERNATE_DIFFUSE_MAP  = 1, +        NORMAL_MAP             = 1, +        SPECULAR_MAP           = 2, +        // Channels for PBR textures +        BASECOLOR_MAP          = 3,          METALLIC_ROUGHNESS_MAP = 4, -        GLTF_NORMAL_MAP           = 5, -        EMISSIVE_MAP          = 6, -        NUM_TEXTURE_CHANNELS  = 7, +        GLTF_NORMAL_MAP        = 5, +        EMISSIVE_MAP           = 6, +        // Total number of channels +        NUM_TEXTURE_CHANNELS   = 7,      };      enum eVolumeTexIndex : U8 diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 2eb7c21f77..02afcf12c6 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -794,6 +794,18 @@ void LLVertexBuffer::setLabel(const char* label) {  }  #endif +void LLVertexBuffer::clone(LLVertexBuffer& target) const +{ +    target.mTypeMask = mTypeMask; +    target.mIndicesType = mIndicesType; +    target.mIndicesStride = mIndicesStride; +    if (target.getNumVerts() != getNumVerts() || +        target.getNumIndices() != getNumIndices()) +    { +        target.allocateBuffer(getNumVerts(), getNumIndices()); +    } +} +  void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const  {      llassert(validateRange(start, end, count, indices_offset)); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 49500e28ce..4ada0c335b 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -163,13 +163,13 @@ public:      // set for rendering      // assumes (and will assert on) the following: -    //      - this buffer has no pending unampBuffer call +    //      - this buffer has no pending unmapBuffer call      //      - a shader is currently bound      //      - This buffer has sufficient attributes within it to satisfy the needs of the currently bound shader      void    setBuffer();      // Only call each getVertexPointer, etc, once before calling unmapBuffer() -    // call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer() +    // call unmapBuffer() after calls to getXXXStrider() before any calls to setBuffer()      // example:      //   vb->getVertexBuffer(verts);      //   vb->getNormalStrider(norms); @@ -218,12 +218,12 @@ public:      U32 getNumIndices() const               { return mNumIndices; }      U32 getTypeMask() const                 { return mTypeMask; } -    bool hasDataType(AttributeType type) const      { return ((1 << type) & getTypeMask()); } +    bool hasDataType(AttributeType type) const { return ((1 << type) & getTypeMask()); }      U32 getSize() const                     { return mSize; }      U32 getIndicesSize() const              { return mIndicesSize; }      U8* getMappedData() const               { return mMappedData; }      U8* getMappedIndices() const            { return mMappedIndexData; } -    U32 getOffset(AttributeType type) const         { return mOffsets[type]; } +    U32 getOffset(AttributeType type) const { return mOffsets[type]; }      // these functions assume (and assert on) the current VBO being bound      // Detailed error checking can be enabled by setting gDebugGL to true @@ -242,6 +242,7 @@ public:      void setLabel(const char* label);      #endif +    void clone(LLVertexBuffer& target) const;  protected:      U32     mGLBuffer = 0;      // GL VBO handle diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index f73c530ff9..d14a7ffddc 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -514,7 +514,7 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)      mDrawablep->getSpatialGroup()->rebuildGeom();      mDrawablep->getSpatialGroup()->rebuildMesh(); -    if(mVertexBuffer.isNull()) +    if (mVertexBuffer.isNull())      {          return;      } @@ -567,8 +567,20 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)          {              // cheaters sometimes prosper...              // -            mVertexBuffer->setBuffer(); -            mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); +            LLVertexBuffer* vertex_buffer = mVertexBuffer.get(); +            // To display selection markers (white squares with the rounded cross at the center) +            // on faces with GLTF textures we use a spectal vertex buffer with other transforms +            if (const LLTextureEntry* te = getTextureEntry()) +            { +                if (LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial()) +                { +                    vertex_buffer = mVertexBufferGLTF.get(); +                    vertex_buffer->unmapBuffer(); +                } +            } +            // Draw the selection marker using the correctly chosen vertex buffer +            vertex_buffer->setBuffer(); +            vertex_buffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);          }          gGL.popMatrix(); @@ -1144,7 +1156,8 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,                                  const LLMatrix3& mat_norm_in,                                  U16 index_offset,                                  bool force_rebuild, -                                bool no_debug_assert) +                                bool no_debug_assert, +                                bool rebuild_for_gltf)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE;      llassert(verify()); @@ -1202,6 +1215,58 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,          }      } +    const LLTextureEntry* tep = mVObjp->getTE(face_index); +    llassert(tep); +    if (!tep) +        return false; + +    LLGLTFMaterial* gltf_mat = tep->getGLTFRenderMaterial(); +    // To display selection markers (white squares with the rounded cross at the center) +    // on faces with GLTF textures we use a special vertex buffer with other transforms +    if (gltf_mat && !rebuild_for_gltf && tep->isSelected() && mVertexBuffer.notNull()) +    { +        // Create a temporary vertex buffer to provide transforms for GLTF textures +        if (mVertexBufferGLTF.isNull()) +        { +            mVertexBufferGLTF = new LLVertexBuffer(mVertexBuffer->getTypeMask()); +        } + +        // Clone the existing vertex buffer into the temporary one +        mVertexBuffer->clone(*mVertexBufferGLTF); + +        // Recursive call the same function with the argument rebuild_for_gltf set to true +        // This call will make geometry in mVertexBuffer but in fact for mVertexBufferGLTF +        mVertexBufferGLTF.swap(mVertexBufferGLTF, mVertexBuffer); +        getGeometryVolume(volume, face_index, mat_vert_in, mat_norm_in, index_offset, force_rebuild, no_debug_assert, true); +        mVertexBufferGLTF.swap(mVertexBufferGLTF, mVertexBuffer); +    } +    else if (!tep->isSelected() && mVertexBufferGLTF.notNull()) +    { +        // Free the temporary vertex buffer when it is not needed anymore +        mVertexBufferGLTF = nullptr; +    } + +    LLGLTFMaterial::TextureInfo gltf_info_index = (LLGLTFMaterial::TextureInfo)0; +    if (gltf_mat && rebuild_for_gltf) +    { +        switch (LLPipeline::sRenderHighlightTextureChannel) +        { +        case LLRender::BASECOLOR_MAP: +            gltf_info_index = LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR; +            break; +        case LLRender::METALLIC_ROUGHNESS_MAP: +            gltf_info_index = LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS; +            break; +        case LLRender::GLTF_NORMAL_MAP: +            gltf_info_index = LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL; +            break; +        case LLRender::EMISSIVE_MAP: +            gltf_info_index = LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE; +            break; +        default:; // just to make clang happy +        } +    } +      LLStrider<LLVector3> vert;      LLStrider<LLVector2> tex_coords0;      LLStrider<LLVector2> tex_coords1; @@ -1218,7 +1283,7 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,      LLVector3 scale;      if (global_volume)      { -        scale.setVec(1,1,1); +        scale.setVec(1, 1, 1);      }      else      { @@ -1233,7 +1298,6 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,      bool rebuild_tangent = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TANGENT);      bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4); -    const LLTextureEntry *tep = mVObjp->getTE(face_index);      const U8 bump_code = tep ? tep->getBumpmap() : 0;      bool is_static = mDrawablep->isStatic(); @@ -1323,7 +1387,6 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,      LLMaterial* mat = tep->getMaterialParams().get(); -    LLGLTFMaterial* gltf_mat = tep->getGLTFRenderMaterial();      F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; @@ -1334,13 +1397,27 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,      S32 xforms = XFORM_NONE;      // For GLTF, transforms will be applied later -    if (rebuild_tcoord && tep && !gltf_mat) +    if (rebuild_tcoord && tep && (!gltf_mat || rebuild_for_gltf))      { -        r  = tep->getRotation(); -        os = tep->mOffsetS; -        ot = tep->mOffsetT; -        ms = tep->mScaleS; -        mt = tep->mScaleT; +        if (gltf_mat && rebuild_for_gltf) +        { +            // Apply special transformations for mVertexBufferGLTF +            // They are used only to display a face selection marker +            // (white square with a rounded cross at the center) +            const auto& tt = gltf_mat->mTextureTransform[gltf_info_index]; +            r = -tt.mRotation * 2; +            ms = tt.mScale[VX]; +            mt = tt.mScale[VY]; +            os += tt.mOffset[VX] + (ms - 1) / 2; +            ot -= tt.mOffset[VY] + (mt - 1) / 2; +        } +        else +        { +            r = tep->getRotation(); +            tep->getOffset(&os, &ot); +            tep->getScale(&ms, &mt); +        } +          cos_ang = cos(r);          sin_ang = sin(r); @@ -1481,12 +1558,9 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,                      break;                  } -                F32 s_scale = 1.f; -                F32 t_scale = 1.f; -                if( tep ) -                { -                    tep->getScale( &s_scale, &t_scale ); -                } +                F32 s_scale = tep->getScaleS(); +                F32 t_scale = tep->getScaleT(); +                  // Use the nudged south when coming from above sun angle, such                  // that emboss mapping always shows up on the upward faces of cubes when                  // it's noon (since a lot of builders build with the sun forced to noon). @@ -1508,8 +1582,8 @@ bool LLFace::getGeometryVolume(const LLVolume& volume,              bool tex_anim = false; -                LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp; -                tex_mode = vobj->mTexAnimMode; +            LLVOVolume* vobj = (LLVOVolume*)mVObjp.get(); +            tex_mode = vobj->mTexAnimMode;              if (vobj->mTextureAnimp)              { //texture animation is in play, override specular and normal map tex coords with diffuse texcoords diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 917f3aa0b2..7cf256f731 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -161,7 +161,8 @@ public:                              const LLMatrix3& mat_normal,                              U16 index_offset,                              bool force_rebuild = false, -                            bool no_debug_assert = false); +                            bool no_debug_assert = false, +                            bool rebuild_for_gltf = false);      // For avatar      U16          getGeometryAvatar( @@ -266,6 +267,7 @@ public:  private:      LLPointer<LLVertexBuffer> mVertexBuffer; +    LLPointer<LLVertexBuffer> mVertexBufferGLTF;      U32         mState;      LLFacePool* mDrawPoolp; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 2a461ca84b..1b2cffa6c9 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -3580,9 +3580,12 @@ void LLPipeline::postSort(LLCamera &camera)      {          mSelectedFaces.clear(); +        bool tex_index_changed = false;          if (!gNonInteractive)          { -            LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit()); +            LLRender::eTexIndex tex_index = sRenderHighlightTextureChannel; +            setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit()); +            tex_index_changed = sRenderHighlightTextureChannel != tex_index;          }          // Draw face highlights for selected faces. @@ -3604,6 +3607,24 @@ void LLPipeline::postSort(LLCamera &camera)                  }              } func;              LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func); + +            if (tex_index_changed) +            { +                // Rebuild geometry for all selected faces with PBR textures +                for (const LLFace* face : gPipeline.mSelectedFaces) +                { +                    if (const LLViewerObject* vobj = face->getViewerObject()) +                    { +                        if (const LLTextureEntry* tep = vobj->getTE(face->getTEOffset())) +                        { +                            if (tep->getGLTFRenderMaterial()) +                            { +                                gPipeline.markRebuild(face->getDrawable(), LLDrawable::REBUILD_VOLUME); +                            } +                        } +                    } +                } +            }          }      } @@ -3656,28 +3677,31 @@ void render_hud_elements()      gUIProgram.unbind();  } -void LLPipeline::renderHighlights() +static inline void bindHighlightProgram(LLGLSLShader& program)  { -    assertInitialized(); - -    // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) -    // Render highlighted faces. -    LLGLSPipelineAlpha gls_pipeline_alpha; -    LLColor4 color(1.f, 1.f, 1.f, 0.5f); -    disableLights(); -      if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))      { -        gHighlightProgram.bind(); -        gGL.diffuseColor4f(1,1,1,0.5f); +        program.bind(); +        gGL.diffuseColor4f(1, 1, 1, 0.5f);      } +} -    if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && !mFaceSelectImagep) -        { -            mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT); -        } +static inline void unbindHighlightProgram(LLGLSLShader& program) +{ +    if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0) +    { +        program.unbind(); +    } +} -    if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::DIFFUSE_MAP)) +void LLPipeline::renderSelectedFaces(const LLColor4& color) +{ +    if (!mFaceSelectImagep) +    { +        mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT); +    } + +    if (mFaceSelectImagep)      {          // Make sure the selection image gets downloaded and decoded          mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); @@ -3693,81 +3717,61 @@ void LLPipeline::renderHighlights()              facep->renderSelected(mFaceSelectImagep, color);          }      } +} -    if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) -    { -        // Paint 'em red! -        color.setVec(1.f, 0.f, 0.f, 0.5f); - -        for (auto facep : mHighlightFaces) -        { -            facep->renderSelected(LLViewerTexture::sNullImagep, color); -        } -    } +void LLPipeline::renderHighlights() +{ +    assertInitialized(); -    // Contains a list of the faces of objects that are physical or -    // have touch-handlers. -    mHighlightFaces.clear(); +    // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) +    // Render highlighted faces. +    LLGLSPipelineAlpha gls_pipeline_alpha; +    disableLights(); -    if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0) +    if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))      { -        gHighlightProgram.unbind(); -    } - +        bindHighlightProgram(gHighlightProgram); -    if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP)) -    { -        color.setVec(1.0f, 0.5f, 0.5f, 0.5f); -        if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) +        if (sRenderHighlightTextureChannel == LLRender::DIFFUSE_MAP || +            sRenderHighlightTextureChannel == LLRender::BASECOLOR_MAP || +            sRenderHighlightTextureChannel == LLRender::METALLIC_ROUGHNESS_MAP || +            sRenderHighlightTextureChannel == LLRender::GLTF_NORMAL_MAP || +            sRenderHighlightTextureChannel == LLRender::EMISSIVE_MAP || +            sRenderHighlightTextureChannel == LLRender::NUM_TEXTURE_CHANNELS)          { -            gHighlightNormalProgram.bind(); -            gGL.diffuseColor4f(1,1,1,0.5f); +            static const LLColor4 highlight_selected_color(1.f, 1.f, 1.f, 0.5f); +            renderSelectedFaces(highlight_selected_color);          } -        mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); - -        for (auto facep : mSelectedFaces) +        // Paint 'em red! +        static const LLColor4 highlight_face_color(1.f, 0.f, 0.f, 0.5f); +        for (auto facep : mHighlightFaces)          { -            if (!facep || facep->getDrawable()->isDead()) -            { -                LL_ERRS() << "Bad face on selection" << LL_ENDL; -                return; -            } - -            facep->renderSelected(mFaceSelectImagep, color); +            facep->renderSelected(LLViewerTexture::sNullImagep, highlight_face_color);          } -        if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) -        { -            gHighlightNormalProgram.unbind(); -        } +        unbindHighlightProgram(gHighlightProgram);      } -    if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP)) -    { -        color.setVec(0.0f, 0.3f, 1.0f, 0.8f); -        if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) -        { -            gHighlightSpecularProgram.bind(); -            gGL.diffuseColor4f(1,1,1,0.5f); -        } - -        mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); +    // Contains a list of the faces of objects that are physical or +    // have touch-handlers. +    mHighlightFaces.clear(); -        for (auto facep : mSelectedFaces) +    if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) +    { +        if (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP)          { -            if (!facep || facep->getDrawable()->isDead()) -            { -                LL_ERRS() << "Bad face on selection" << LL_ENDL; -                return; -            } - -            facep->renderSelected(mFaceSelectImagep, color); +            static const LLColor4 highlight_normal_color(1.0f, 0.5f, 0.5f, 0.5f); +            bindHighlightProgram(gHighlightNormalProgram); +            renderSelectedFaces(highlight_normal_color); +            unbindHighlightProgram(gHighlightNormalProgram);          } - -        if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) +        else if (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP)          { -            gHighlightSpecularProgram.unbind(); +            static const LLColor4 highlight_specular_color(0.0f, 0.3f, 1.0f, 0.8f); +            bindHighlightProgram(gHighlightSpecularProgram); +            renderSelectedFaces(highlight_specular_color); +            unbindHighlightProgram(gHighlightSpecularProgram);          }      }  } @@ -6256,7 +6260,10 @@ bool LLPipeline::getRenderHighlights()  // static  void LLPipeline::setRenderHighlightTextureChannel(LLRender::eTexIndex channel)  { -    sRenderHighlightTextureChannel = channel; +    if (channel != sRenderHighlightTextureChannel) +    { +        sRenderHighlightTextureChannel = channel; +    }  }  LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 6c79d20149..4164474238 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -342,6 +342,7 @@ public:      void renderHighlight(const LLViewerObject* obj, F32 fade);      void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, bool depth_clamp); +    void renderSelectedFaces(const LLColor4& color);      void renderHighlights();      void renderDebug();      void renderPhysicsDisplay();  | 
