void UVertexPainterBPLibrary::PaintVertexColorByIndex(UStaticMeshComponent* StaticMeshComponent, FColor LinearColor, int Index, int LODIndex)
{
if (!StaticMeshComponent || !StaticMeshComponent->GetStaticMesh()) {
return;
}
const int LODNum = StaticMeshComponent->GetStaticMesh()->GetNumLODs();
StaticMeshComponent->SetLODDataCount(LODNum, LODNum);
if (!StaticMeshComponent->LODData.IsValidIndex(LODIndex)) {
return;
}
FStaticMeshComponentLODInfo& LODInfo = StaticMeshComponent->LODData[LODIndex];
const int32 VertexNum = StaticMeshComponent->GetStaticMesh()->GetRenderData()->LODResources[LODIndex].GetNumVertices();
if (Index < 0 || Index >= VertexNum) {
return;
}
TArray<FColor> VertexColors;
LODInfo.OverrideVertexColors->GetVertexColors(VertexColors);
VertexColors[Index] = LinearColor;
LODInfo.OverrideVertexColors = new FColorVertexBuffer;
LODInfo.OverrideVertexColors->InitFromColorArray(VertexColors);
BeginInitResource(LODInfo.OverrideVertexColors);
}
首先区别一下StaticMesh和StaticMeshComponent
StaticMesh是模型本身
直接修改StaticMesh的内容,所有StaticMeshComponent实例都会产生变化
而修改StaticMeshComponent直会对实例产生影响不会对StaticMesh有任何修改
1、要修改顶点着色的StaticMeshCommponent
4、LOD的下标,根据距离不同启用不同的LOD,对应顶点数量也会发生变化。
总结:
if (!StaticMeshComponent || !StaticMeshComponent->GetStaticMesh()) {
return;
}
如果StaticMeshComponent为空,或者StaticMeshComponent对应的StaticMesh为空,则退出函数执行
const int LODNum = StaticMeshComponent->GetStaticMesh()->GetNumLODs();
StaticMeshComponent->SetLODDataCount(LODNum, LODNum);
获取StaticMeshComponent所使用的StaticMesh的LOD数量,将之LOD数量设置为,StaticMeshComponent的LOD上
if (!StaticMeshComponent->LODData.IsValidIndex(LODIndex)) {
return;
}
FStaticMeshComponentLODInfo& LODInfo = StaticMeshComponent->LODData[LODIndex];
const int32 VertexNum = StaticMeshComponent->GetStaticMesh()->GetRenderData()->LODResources[LODIndex].GetNumVertices();
USTRUCT()
struct FStaticMeshComponentLODInfo
{
GENERATED_USTRUCT_BODY()
/** Uniquely identifies this LOD's built map data. */
FGuid MapBuildDataId;
/** Used during deserialization to temporarily store legacy lightmap data. */
FMeshMapBuildData* LegacyMapBuildData;
/**
* Transient override lightmap data, used by landscape grass.
* Be sure to add your component to UMapBuildDataRegistry::CleanupTransientOverrideMapBuildData() for proper cleanup
* so that you don't get stale rendering resource references if the underlying MapBuildData is gone (lighting scenario changes, new static lighting build, etc.)
*/
TUniquePtr<FMeshMapBuildData> OverrideMapBuildData;
/** Vertex data cached at the time this LOD was painted, if any */
TArray<struct FPaintedVertex> PaintedVertices;
/** Vertex colors to use for this mesh LOD */
FColorVertexBuffer* OverrideVertexColors;
/** Information for each section about what range of PreCulledIndexBuffer to use. If no preculled index data is available, PreCulledSections will be empty. */
TArray<FPreCulledStaticMeshSection> PreCulledSections;
FRawStaticIndexBuffer PreCulledIndexBuffer;
/**
* Owner of this FStaticMeshComponentLODInfo
* Warning, can be NULL for a component created via SpawnActor off of a blueprint default (LODData will be created without a call to SetLODDataCount).
*/
class UStaticMeshComponent* OwningComponent;
/** Default constructor */
FStaticMeshComponentLODInfo();
FStaticMeshComponentLODInfo(UStaticMeshComponent* InOwningComponent);
/** Destructor */
~FStaticMeshComponentLODInfo();
/** Delete existing resources */
void CleanUp();
/**
* Ensure this LODInfo has a valid MapBuildDataId GUID.
* @param LodIndex Index of the LOD this LODInfo represents.
* @return true if a new GUID was created, false otherwise.
*/
ENGINE_API bool CreateMapBuildDataId(int32 LodIndex);
/**
* Enqueues a rendering command to release the vertex colors.
* The game thread must block until the rendering thread has processed the command before deleting OverrideVertexColors.
*/
ENGINE_API void BeginReleaseOverrideVertexColors();
ENGINE_API void ReleaseOverrideVertexColorsAndBlock();
void ReleaseResources();
/** Methods for importing and exporting the painted vertex array to text */
void ExportText(FString& ValueStr);
void ImportText(const TCHAR** SourceText);
/** Serializer. */
friend FArchive& operator<<(FArchive& Ar,FStaticMeshComponentLODInfo& I);
private:
/** Purposely hidden */
FStaticMeshComponentLODInfo &operator=( const FStaticMeshComponentLODInfo &rhs ) { check(0); return *this; }
};
该结构体内有对应LOD的顶点颜色
if (Index < 0 || Index >= VertexNum) {
return;
}
如果顶点个数不合法,则不执行后续逻辑
TArray<FColor> VertexColors;
LODInfo.OverrideVertexColors->GetVertexColors(VertexColors);
VertexColors[Index] = LinearColor;
LODInfo.OverrideVertexColors = new FColorVertexBuffer;
LODInfo.OverrideVertexColors->InitFromColorArray(VertexColors);
BeginInitResource(LODInfo.OverrideVertexColors);
记得用这个函数加对应模块
“RenderCore”
总结:就是把LODInfo.OverrideVertexColors重新刷新颜色
void UVertexPainterBPLibrary::PaintVertexColorByIndex(UStaticMeshComponent* StaticMeshComponent, FColor LinearColor, int Index, int LODIndex)
{
if (!StaticMeshComponent || !StaticMeshComponent->GetStaticMesh()) {
return;
}
const int LODNum = StaticMeshComponent->GetStaticMesh()->GetNumLODs();
StaticMeshComponent->SetLODDataCount(LODNum, LODNum);
if (!StaticMeshComponent->LODData.IsValidIndex(LODIndex)) {
return;
}
FStaticMeshComponentLODInfo& LODInfo = StaticMeshComponent->LODData[LODIndex];
FStaticMeshLODResourcesArray& LODResourcesArray = StaticMeshComponent->GetStaticMesh()->GetRenderData()->LODResources;
const int32 VertexNum = LODResourcesArray[LODIndex].GetNumVertices();
if (Index < 0 || Index >= VertexNum) {
return;
}
TArray<FColor> VertexColors;
if (LODInfo.OverrideVertexColors) {
LODInfo.OverrideVertexColors->GetVertexColors(VertexColors);
}
else {
if (LODResourcesArray[LODIndex].bHasColorVertexData) {
LODResourcesArray[LODIndex].VertexBuffers.ColorVertexBuffer.GetVertexColors(VertexColors);
}
else {
VertexColors.Init(FColor::White, VertexNum);
}
}
VertexColors.SetNum(VertexNum);
VertexColors[Index] = LinearColor;
LODInfo.OverrideVertexColors = new FColorVertexBuffer;
LODInfo.OverrideVertexColors->InitFromColorArray(VertexColors);
BeginInitResource(LODInfo.OverrideVertexColors);
}
增加了一部分初始化LODInfo.OverrideVertexColors信息
TArray<FColor> UVertexPainterBPLibrary::GetVertexColorsInLOD(UStaticMeshComponent* StaticMeshComponent, int32 LODIndex) {
TArray<FColor> VertexColors;
if (!StaticMeshComponent || !StaticMeshComponent->GetStaticMesh()) {
return VertexColors;
}
const int LODNum = StaticMeshComponent->GetStaticMesh()->GetNumLODs();
if (LODIndex < 0 || LODIndex >= LODNum) {
return VertexColors;
}
FStaticMeshComponentLODInfo& LODInfo = StaticMeshComponent->LODData[LODIndex];
FStaticMeshLODResourcesArray& LODResourcesArray = StaticMeshComponent->GetStaticMesh()->GetRenderData()->LODResources;
const int32 VertexNum = LODResourcesArray[LODIndex].GetNumVertices();
if (StaticMeshComponent->LODData.IsValidIndex(LODIndex)) {
if (LODInfo.OverrideVertexColors) {
LODInfo.OverrideVertexColors->GetVertexColors(VertexColors);
VertexColors.SetNum(VertexNum);
return VertexColors;
}
}
{
if (LODResourcesArray[LODIndex].bHasColorVertexData) {
LODResourcesArray[LODIndex].VertexBuffers.ColorVertexBuffer.GetVertexColors(VertexColors);
}
else {
VertexColors.Init(FColor::White, VertexNum);
}
}
VertexColors.SetNum(VertexNum);
return VertexColors;
}
void UVertexPainterBPLibrary::PaintVertexColorOnSphere(UStaticMeshComponent* StaticMeshComponent, FColor LinearColor, float Radius, FVector Position)
{
if (!StaticMeshComponent || !StaticMeshComponent->GetStaticMesh()) {
return;
}
const int LODNum = StaticMeshComponent->GetStaticMesh()->GetNumLODs();
StaticMeshComponent->SetLODDataCount(LODNum, LODNum);
const FTransform& LocalToWorld = StaticMeshComponent->GetComponentTransform();
int LODIndex = 0;
for (FStaticMeshComponentLODInfo& LODInfo : StaticMeshComponent->LODData) {
const FPositionVertexBuffer& PositionVertexBuffer = StaticMeshComponent->GetStaticMesh()->GetRenderData()->
LODResources[LODIndex].VertexBuffers.PositionVertexBuffer;
int VertexNum = PositionVertexBuffer.GetNumVertices();
TArray<FColor> VertexColors = GetVertexColorsInLOD(StaticMeshComponent, LODIndex++);
for (int i = 0; i < VertexNum; i++) {
FVector VertexPosition = UKismetMathLibrary::TransformLocation(LocalToWorld, FVector(PositionVertexBuffer.VertexPosition(i)));
float NormalizedDistance = UKismetMathLibrary::Vector_Distance(VertexPosition, Position)/Radius;
if (NormalizedDistance <= 1) {
VertexColors[i] = LinearColor;
}
}
LODInfo.OverrideVertexColors = new FColorVertexBuffer;
LODInfo.OverrideVertexColors->InitFromColorArray(VertexColors);
BeginInitResource(LODInfo.OverrideVertexColors);
}
StaticMeshComponent->MarkRenderStateDirty();
StaticMeshComponent->bDisallowMeshPaintPerInstance = true;
}
TArray<FColor> VertexColors;
if (!StaticMeshComponent || !StaticMeshComponent->GetStaticMesh()) {
return VertexColors;
}
const int LODNum = StaticMeshComponent->GetStaticMesh()->GetNumLODs();
if (LODIndex < 0 || LODIndex >= LODNum) {
return VertexColors;
}
FStaticMeshComponentLODInfo& LODInfo = StaticMeshComponent->LODData[LODIndex];
FStaticMeshLODResourcesArray& LODResourcesArray = StaticMeshComponent->GetStaticMesh()->GetRenderData()->LODResources;
const int32 VertexNum = LODResourcesArray[LODIndex].GetNumVertices();
这里拿到LOD信息,然后获取LOD资源的数组,最后拿到顶点的数量
if (StaticMeshComponent->LODData.IsValidIndex(LODIndex)) {
if (LODInfo.OverrideVertexColors) {
LODInfo.OverrideVertexColors->GetVertexColors(VertexColors);
VertexColors.SetNum(VertexNum);
return VertexColors;
}
}
{
if (LODResourcesArray[LODIndex].bHasColorVertexData) {
LODResourcesArray[LODIndex].VertexBuffers.ColorVertexBuffer.GetVertexColors(VertexColors);
}
else {
VertexColors.Init(FColor::White, VertexNum);
}
}
VertexColors.SetNum(VertexNum);
return VertexColors;
if (!StaticMeshComponent || !StaticMeshComponent->GetStaticMesh()) {
return;
}
const int LODNum = StaticMeshComponent->GetStaticMesh()->GetNumLODs();
StaticMeshComponent->SetLODDataCount(LODNum, LODNum);
从StaticMesh的LOD数量设置到StaticMeshComponent里面去
const FTransform& LocalToWorld = StaticMeshComponent->GetComponentTransform();
int LODIndex = 0;
for (FStaticMeshComponentLODInfo& LODInfo : StaticMeshComponent->LODData) {
const FPositionVertexBuffer& PositionVertexBuffer = StaticMeshComponent->GetStaticMesh()->GetRenderData()->
LODResources[LODIndex].VertexBuffers.PositionVertexBuffer;
int VertexNum = PositionVertexBuffer.GetNumVertices();
TArray<FColor> VertexColors = GetVertexColorsInLOD(StaticMeshComponent, LODIndex++);
for (int i = 0; i < VertexNum; i++) {
FVector VertexPosition = UKismetMathLibrary::TransformLocation(LocalToWorld, FVector(PositionVertexBuffer.VertexPosition(i)));
float NormalizedDistance = UKismetMathLibrary::Vector_Distance(VertexPosition, Position)/Radius;
if (NormalizedDistance <= 1) {
VertexColors[i] = LinearColor;
}
}
LODInfo.OverrideVertexColors = new FColorVertexBuffer;
LODInfo.OverrideVertexColors->InitFromColorArray(VertexColors);
BeginInitResource(LODInfo.OverrideVertexColors);
}
先开始拿到顶点缓冲位置,这个信息是在LODResources里面,LOD里面有Vertex信息,当然顶点的位置信息也包括在里面
FPositionVertexBuffer是继承自VertexBuffer的
接下来TArray<FColor>获取到顶点颜色的所有颜色,通过第一个函数获取,就不赘述
接下来就是对每个顶点进行赋值颜色信息,通过TransformLocation函数,可以将本地的VertexPosition转化为世界场景坐标
float NormalizedDistance = UKismetMathLibrary::Vector_Distance(VertexPosition, Position)/Radius;
if (NormalizedDistance <= 1) {
VertexColors[i] = LinearColor;
}
最后这里都讲过
LODInfo.OverrideVertexColors = new FColorVertexBuffer;
LODInfo.OverrideVertexColors->InitFromColorArray(VertexColors);
BeginInitResource(LODInfo.OverrideVertexColors);
StaticMeshComponent->MarkRenderStateDirty();
StaticMeshComponent->bDisallowMeshPaintPerInstance = true;
TArray<FColor> UVertexPainterBPLibrary::GetSkeletalVertexColorsInLOD(USkeletalMeshComponent* SkeletalMeshComponent, int32 LODIndex) {
TArray<FColor> VertexColors;
if (!SkeletalMeshComponent || !SkeletalMeshComponent->SkeletalMesh) {
return VertexColors;
}
const int LODNum = SkeletalMeshComponent->SkeletalMesh->GetLODNum();
if (LODIndex < 0 || LODIndex >= LODNum) {
return VertexColors;
}
FSkelMeshComponentLODInfo& LODInfo = SkeletalMeshComponent->LODInfo[LODIndex];
FSkeletalMeshLODRenderData& LODResourcesArray = SkeletalMeshComponent->SkeletalMesh->GetResourceForRendering()->LODRenderData[LODIndex];
const int32 VertexNum = LODResourcesArray.GetNumVertices();
if (SkeletalMeshComponent->LODInfo.IsValidIndex(LODIndex)) {
if (LODInfo.OverrideVertexColors) {
LODInfo.OverrideVertexColors->GetVertexColors(VertexColors);
VertexColors.SetNum(VertexNum);
return VertexColors;
}
}
{
VertexColors.Init(FColor::White, VertexNum);
}
VertexColors.SetNum(VertexNum);
return VertexColors;
}
void UVertexPainterBPLibrary::PaintVertexColorOnSkeletal(USkeletalMeshComponent* SkeletalMeshComponent, FColor LinearColor, float Radius, FVector Position) {
if (!SkeletalMeshComponent || !SkeletalMeshComponent->SkeletalMesh) {
return;
}
SkeletalMeshComponent->InitLODInfos();
const FTransform& LocalToWorld = SkeletalMeshComponent->GetComponentTransform();
int LODIndex = 0;
for (FSkelMeshComponentLODInfo& LODInfo : SkeletalMeshComponent->LODInfo) {
FSkeletalMeshLODRenderData& LODRenderData = SkeletalMeshComponent->SkeletalMesh->GetResourceForRendering()->LODRenderData[LODIndex];
const int VertexNum = LODRenderData.GetNumVertices();
FSkinWeightVertexBuffer& SkinWeightVertexBuffer = LODRenderData.SkinWeightVertexBuffer;
TArray<FColor> VertexColors = GetSkeletalVertexColorsInLOD(SkeletalMeshComponent, LODIndex++);
for (int i = 0; i < VertexNum; i++) {
FVector VertexPosition = UKismetMathLibrary::TransformLocation(LocalToWorld, FVector(USkeletalMeshComponent::GetSkinnedVertexPosition(SkeletalMeshComponent, i,
LODRenderData, SkinWeightVertexBuffer)));
float NormalizedDistance = UKismetMathLibrary::Vector_Distance(VertexPosition, Position) / Radius;
if (NormalizedDistance <= 1) {
VertexColors[i] = LinearColor;
}
}
LODInfo.OverrideVertexColors = new FColorVertexBuffer;
LODInfo.OverrideVertexColors->InitFromColorArray(VertexColors);
BeginInitResource(LODInfo.OverrideVertexColors);
}
SkeletalMeshComponent->MarkRenderStateDirty();
}
原文地址:https://blog.csdn.net/qqQQqsadfj/article/details/134710003
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_18979.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!