#1922 Make PBR scale and offset crosshair work like Texture crosshair do

master
Alexander Gavriliuk 2024-08-07 20:56:10 +02:00 committed by Guru
parent e20e387d48
commit 17f7b439d6
7 changed files with 211 additions and 111 deletions

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);
}
}
static inline void unbindHighlightProgram(LLGLSLShader& program)
{
if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
{
program.unbind();
}
}
void LLPipeline::renderSelectedFaces(const LLColor4& color)
{
if (!mFaceSelectImagep)
{
mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT);
}
if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && !mFaceSelectImagep)
{
mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT);
}
if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::DIFFUSE_MAP))
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);
}
}
}
void LLPipeline::renderHighlights()
{
assertInitialized();
// Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
// Render highlighted faces.
LLGLSPipelineAlpha gls_pipeline_alpha;
disableLights();
if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
{
// Paint 'em red!
color.setVec(1.f, 0.f, 0.f, 0.5f);
bindHighlightProgram(gHighlightProgram);
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)
{
static const LLColor4 highlight_selected_color(1.f, 1.f, 1.f, 0.5f);
renderSelectedFaces(highlight_selected_color);
}
// Paint 'em red!
static const LLColor4 highlight_face_color(1.f, 0.f, 0.f, 0.5f);
for (auto facep : mHighlightFaces)
{
facep->renderSelected(LLViewerTexture::sNullImagep, color);
facep->renderSelected(LLViewerTexture::sNullImagep, highlight_face_color);
}
unbindHighlightProgram(gHighlightProgram);
}
// Contains a list of the faces of objects that are physical or
// have touch-handlers.
mHighlightFaces.clear();
if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
{
gHighlightProgram.unbind();
}
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::NORMAL_MAP)
{
gHighlightNormalProgram.bind();
gGL.diffuseColor4f(1,1,1,0.5f);
static const LLColor4 highlight_normal_color(1.0f, 0.5f, 0.5f, 0.5f);
bindHighlightProgram(gHighlightNormalProgram);
renderSelectedFaces(highlight_normal_color);
unbindHighlightProgram(gHighlightNormalProgram);
}
mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA);
for (auto facep : mSelectedFaces)
else if (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP)
{
if (!facep || facep->getDrawable()->isDead())
{
LL_ERRS() << "Bad face on selection" << LL_ENDL;
return;
}
facep->renderSelected(mFaceSelectImagep, color);
}
if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
{
gHighlightNormalProgram.unbind();
}
}
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);
for (auto facep : mSelectedFaces)
{
if (!facep || facep->getDrawable()->isDead())
{
LL_ERRS() << "Bad face on selection" << LL_ENDL;
return;
}
facep->renderSelected(mFaceSelectImagep, color);
}
if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
{
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,

View File

@ -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();