UE4 顶点着色 学习笔记

这篇具有很好参考价值的文章主要介绍了UE4 顶点着色 学习笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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是模型本身

而StaticMeshComponent是模型出来的实例

直接修改StaticMesh的内容,所有StaticMeshComponent实例都会产生变化

而修改StaticMeshComponent直会对实例产生影响不会对StaticMesh有任何修改


UE4 顶点着色 学习笔记,ue4,java,服务器


函数参数

1、要修改顶点着色的StaticMeshCommponent

2、第二个顶点所修改成的颜色

3、顶点的下标,具体修改的是哪一个顶点

4、LOD的下标,根据距离不同启用不同的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;
}

如果函数参数的LODIndex是无效的,则不执行函数后续


FStaticMeshComponentLODInfo& LODInfo = StaticMeshComponent->LODData[LODIndex];

const int32 VertexNum = StaticMeshComponent->GetStaticMesh()->GetRenderData()->LODResources[LODIndex].GetNumVertices();

获取StaticMeshComponent的LOD信息

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"

UE4 顶点着色 学习笔记,ue4,java,服务器


总结:就是把LODInfo.OverrideVertexColors重新刷新颜色

最后记住模型加上Vertex Color的材质

UE4 顶点着色 学习笔记,ue4,java,服务器

UE4 顶点着色 学习笔记,ue4,java,服务器

UE4 顶点着色 学习笔记,ue4,java,服务器


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;

这里拿到Component在场景的世界变换信息


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的

UE4 顶点着色 学习笔记,ue4,java,服务器

UE4 顶点着色 学习笔记,ue4,java,服务器

UE4 顶点着色 学习笔记,ue4,java,服务器

顶点数量,顶点位置的信息都在FVertexBuffer里面

接下来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();
}

UE4 顶点着色 学习笔记,ue4,java,服务器

UE4 顶点着色 学习笔记,ue4,java,服务器

最后来一个支持谷歌模型的顶点绘制


UE4 顶点着色 学习笔记,ue4,java,服务器文章来源地址https://www.toymoban.com/news/detail-760152.html

到了这里,关于UE4 顶点着色 学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • UE4 HLSL学习笔记

    在Custom配置对应ush文件路径 在HLSL中写入对应代码 Custom里面增加两个Input,名字必须和ush文件内的未知变量名字一样 然后就对应输出对应效果的颜色 这就是简单的加法运算 减法同理: 乘法除法同理 HLSL取最小值 HLSL取最大值 绝对值: 取余: 四舍五入 Pow运算: 材质里面是

    2024年02月06日
    浏览(39)
  • UE4 初始化全局着色器库所需的游戏文件缺失

    ​ 解决的方法是打包的主场景牵扯到的子场景放到同一个文件夹下 ​ ​ 如果移动了场景,会出现一个同名的壳(node),如果还改名了即使在一个文件夹下也会导致这个问题,解决办法是移动完之后右键Content点击fix up···

    2024年02月11日
    浏览(38)
  • UE4 体积云制作 学习笔记

    首先Noise本来就是一张噪点图 云的扰动不能太大,将Scale调小,并将InputMin调整为0 形成这样一张扰动图 扰动需要根据材质在世界的位置进行调整,所以Position需要加上WorldPosition 材质在不同世界位置,噪点不同 除以一个数,相当于原来0~1范围的贴图变成了0~0.2范围的贴图,贴

    2024年02月08日
    浏览(40)
  • UE4入门级蓝图学习笔记整理

    学习到的新结点及遇到的一些问题: 时间轴 :时间为变量的输出一个/多个数值的有迹可循的函数图 Gate 像门一样。只有当门是Open状态才会执行Exit后面的代码。Open开门;Close关门;Toggle开门和关门交替 FlipFlop 开关节点 ,反复执行,这个节点就简化了某些场合下使用Branch节点

    2024年02月07日
    浏览(36)
  • UE4 地形编辑基础知识 学习笔记

    之前自己写过这样的功能,今天看到一个UE现成的 点击地形,选择样条 按住CTRL键+点击屏幕中某一个点会在场景内生成一个这样的图标 再点两次,会生成B样条的绿线条 点击+号再选择一个模型,会生成对应的链条状的mesh 拉高最远处的一个图标抬高 如果想地形贴合该mesh,则

    2024年02月11日
    浏览(42)
  • UE4学习笔记——解决动画重定向后整体位移消失问题

    我用到的动作资源是一个双手剑的动画集合,用到的是小白人标准骨骼(其实不标准,原作者添加了weapon骨骼即双手剑的系列骨骼,但是没什么影响),而我想要重定向的目标来自虚幻商城中的免费资源“虚幻争霸:锐斯”的改动版(①我将锐斯的模型导入Blender进行了修改,

    2024年02月03日
    浏览(43)
  • 《使用Unreal Engine Python插件进行UE4中的Python开发》学习笔记1

    ·本文为B站系列教学视频 《使用 UnrealEnginPython 插件进行UE4中的Python开发》 ——《 Day 01 初识 UnrealEnginePython 》的学习笔记,UP主为腾讯游戏策划、虚幻社区贡献者 世欺子。 本节课对基于虚幻引擎( Unreal Engine )的 Python 集成开发插件 UnrealEnginePython 进行简要介绍,接着在虚幻

    2024年04月11日
    浏览(50)
  • UE4-上传图片到服务器

    由于 VaRest 插件无法满足我们上传表单的需求,在这里需要使用其他库方法。 优点: httplib 库是一个以 C++11 特性编写的库,所以编译器也需要能支持 C++11 的。库在使用时只需包含一个头文件即可,非常方便。 缺点: 此库为线程阻塞,使用时还请注意。 由于上传图片需要提

    2024年02月07日
    浏览(38)
  • 【UE4】多人联机教程(重点笔记)

    1. 创建房间、搜索房间功能 2. 根据指定IP和端口加入游戏 1. 新建一个第三人称角色模板工程 2. 创建一个空白关卡,这里命名为“InitMap” 3. 新建一个控件蓝图,这里命名为“UMG_ConnectMenu” 在关卡蓝图中显示该控件蓝图 打开“UMG_ConnectMenu”,添加如下控件 首先添加创建房间按

    2024年02月14日
    浏览(24)
  • 墨尘 - UE4 入门教程笔记 —— 二

    旋转视图:Alt + 鼠标左键 缩放视图:Alt + 鼠标右键 平移视图:Alt + 鼠标中间 移动:E、缩放:T、R:旋转 撤回:Ctrl + Z 复原视图:Ctrl + shift + Z 转为可编辑对象:C 局部坐标与世界坐标切换:W 循环线选中:双击(确保坐标轴关闭) 打组:Alt + G、取消打组:shift + G 循环切刀工

    2024年02月16日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包