图形渲染记录(模型)

点+ index(三角形)->mesh

各种法线、亮度->材质

这些都在CPU阶段 ,渲染管线开始时由CPU提交给GPU进行绘图

自定义渲染管线:

1.点映射到屏幕空间(变换)(GPU)

2.将屏幕空间的点图元化,如果需要对三角形细分则在图元化后细分,裁剪(硬件进行),深度测试等(此时还没映射到屏幕)(GPU)

此阶段前还可以读取CPU传来的代码(对GPU的语言:shader),逐个顶点操作

3.光栅化:映射到屏幕,并对像素操作(GPU)

在这个光栅化阶段后,也可以读取CPU传来的代码,逐个像素操作,再进行光栅化

4.深度测试并将最好结果合并放入后缓冲区,交给交换链进行下一步操作

DX12渲染管线

应用程序阶段——CPU(内存)

几何阶段——变换

光栅阶段——图元装配、光栅化和插值、像素操作、帧缓冲区

流输出阶段

1.输入装配阶段:顶点、索引(几何元素/几何图元)

2.顶点着色阶段:顶点着色器(顶点数据、变换、光照、纹理贴图——法线和置换)(Shader)

3.外壳着色阶段:单个表面分解为许多三角形        *

4.曲面细分阶段:细化三角形

5.域着色阶段:各个域样本对于的顶点位置        (Shader)

6.几何着色阶段(可选):点或者线扩展为四边形

7.光栅化阶段:将三角形生成像素

8.像素着色阶段:针对像素进行编程处理        (Shader)

装配阶段

基类

储存顶点信息和面(Index)的结构体

struct FVertex
{
	FVertex(const XMFLOAT3& InPos, const XMFLOAT4& InColor);
	XMFLOAT3 Position;
	XMFLOAT4 Color;
	XMFLOAT3 Normal;
	XMFLOAT3 UTangent;
};

struct FMeshRenderingData
{
	vector<FVertex> VertexData;
	vector<uint16_t> IndexData;
};

Rendering基类:提供渲染接口,实现解耦合

#pragma once
#include"../../Core/Engine.h"
#include"Engine/EngineMinimal.h"

class IRenderingInterface
{
	friend class FWindowsEngine;
public:
	IRenderingInterface();
	virtual ~IRenderingInterface();

	virtual void Draw(float DeltaTime);

	bool operator ==(const IRenderingInterface& tmp)
	{
		return guid_equal(&Guid, &tmp.Guid);
	}

	simple_c_guid GetGuid() { return Guid; }
protected:
	ComPtr<ID3D12Device> GetD3D12Device();
	ComPtr<ID3D12GraphicsCommandList> GetGraphicsCommandList();
	ComPtr<ID3D12Resource> ConstructDefaultBuffer(ComPtr<ID3D12Resource>& OutTmpBuffer,const void* InData,UINT64 DataSize);

private:
	static vector<IRenderingInterface*> RenderingInterface;
	simple_c_guid Guid;
};

Mesh基类:继承Rendering,是所以模型的基类。对顶点缓冲区和索引缓冲区初始化

#pragma once
#include"../../Rending/Core/Rendering.h"
#include"MeshType.h"
class FRenderingResoucesUpdate;

struct FObjectTrasformation
{
	FObjectTrasformation();

	XMFLOAT4X4 World;
};
class FMesh :public IRenderingInterface
{
public:
	FMesh();
	virtual void Init();

	virtual void BuildMesh(const FMeshRenderingData* InMeshRenderingData);
	virtual void Draw(float DeltaTime);

	static FMesh* CreateMesh(const FMeshRenderingData* InMeshRenderingData);

	D3D12_VERTEX_BUFFER_VIEW GetVertexBufferView();
	D3D12_INDEX_BUFFER_VIEW GetIndexBufferView();
//Vertex & Index args
protected:
	UINT VertexSizeInBytes;
	UINT VertexStrideInBytes;
	UINT IndexSizeInBytes;
	DXGI_FORMAT IndexFormat;
	UINT IndexSize;
protected:
	ComPtr<ID3DBlob> CPUVertexBufferPtr;
	ComPtr<ID3DBlob> CPUIndexBufferPtr;

	ComPtr<ID3D12Resource> GPUVertexBufferPtr;
	ComPtr<ID3D12Resource> GPUIndexBufferPtr;

	ComPtr<ID3D12Resource> VertexBufferTmpPtr;
	ComPtr<ID3D12Resource> IndexBufferTmpPtr;

	shared_ptr<FRenderingResoucesUpdate> ObjectConstants;
	ComPtr<ID3D12DescriptorHeap> CBVHeap;
};

//常量缓冲区的信息
class FRenderingResoucesUpdate :public enable_shared_from_this <FRenderingResoucesUpdate >
{
public:
	FRenderingResoucesUpdate();
	~FRenderingResoucesUpdate();

	void Init(ComPtr<ID3D12Device> InDevice, UINT InDataSize, UINT InDataCount);

	void Update(UINT Index, const void* InData);

	UINT GetConstantBufferBytesSize(UINT InBytesSize);
	UINT GetConstantBufferBytesSize();

	ID3D12Resource* GetBuffer() { return UpdateBuffer.Get(); }
private:
	ComPtr<ID3D12Resource> UpdateBuffer;
	BYTE* Data;
	UINT ElementSize;
};

常量缓冲区

常量缓冲区是GPU资源(ID3D12Resource),其数据内容可以在着色器程序中引用,方便了C++和Shader的通信。

创建常量缓冲区

//常量缓冲区
// CBV 栈创建
D3D12_DESCRIPTOR_HEAP_DESC CBVDescriptorHeapDesc;
CBVDescriptorHeapDesc.NumDescriptors = 1;
CBVDescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
CBVDescriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
CBVDescriptorHeapDesc.NodeMask = 0;//默认
ANALYSIS_HRESULT(GetD3D12Device()->CreateDescriptorHeap(
	&CBVDescriptorHeapDesc,
	IID_PPV_ARGS(CBVHeap.GetAddressOf())));

///
ObjectConstants = make_shared<FRenderingResoucesUpdate>();
ObjectConstants->Init(GetD3D12Device().Get(),sizeof(FObjectTrasformation),1);
D3D12_GPU_VIRTUAL_ADDRESS GPUVADD = ObjectConstants.get()->GetBuffer()->GetGPUVirtualAddress();
D3D12_CONSTANT_BUFFER_VIEW_DESC ConstantBVD;
ConstantBVD.BufferLocation = GPUVADD;
ConstantBVD.SizeInBytes = ObjectConstants->GetConstantBufferBytesSize();

GetD3D12Device()->CreateConstantBufferView(
	&ConstantBVD,
	CBVHeap->GetCPUDescriptorHandleForHeapStart()
	);

根签名

帮着色器提供在渲染流水线需要的所有资源

根参数可以是 根常量、根描述符、描述符表(可以装CBV)

这里使用描述符表

//构建根签名
CD3DX12_ROOT_PARAMETER RootParam[1];

//CBV描述表
/*	D3D12_DESCRIPTOR_RANGE_TYPE_SRV = 0,
	D3D12_DESCRIPTOR_RANGE_TYPE_UAV = (D3D12_DESCRIPTOR_RANGE_TYPE_SRV + 1),//无序访问视图
	D3D12_DESCRIPTOR_RANGE_TYPE_CBV = (D3D12_DESCRIPTOR_RANGE_TYPE_UAV + 1),//常量缓冲区的视图
	D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER = (D3D12_DESCRIPTOR_RANGE_TYPE_CBV + 1)*/
CD3DX12_DESCRIPTOR_RANGE DescRangeCBV;
DescRangeCBV.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV,1,0);//0:0号着色器
RootParam[0].InitAsDescriptorTable(1, &DescRangeCBV);

/*	D3D12_ROOT_SIGNATURE_FLAG_NONE = 0,
	D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT = 0x1,//为当前程序输入汇编器,顶点缓存绑定在输入布局
	D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS = 0x2,//拒接顶点着色器访问的根签名
	D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS = 0x4,//拒接外壳着色器访问的根签名
	D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS = 0x8,//拒接域着色器访问的根签名
	D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS = 0x10,//拒接几何着色器访问的根签名
	D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS = 0x20,//拒接像素着色器访问的根签名
	D3D12_ROOT_SIGNATURE_FLAG_ALLOW_STREAM_OUTPUT = 0x40,//流输出有关
	D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE = 0x80,//和光线追踪着色器一起使用,不能和其他的结合使用
	D3D12_ROOT_SIGNATURE_FLAG_DENY_AMPLIFICATION_SHADER_ROOT_ACCESS = 0x100,//拒接放大着色器访问的根签名
	D3D12_ROOT_SIGNATURE_FLAG_DENY_MESH_SHADER_ROOT_ACCESS = 0x200,//拒接顶点着色器访问的根签名拒绝网格着色器
	D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED = 0x400,
	D3D12_ROOT_SIGNATURE_FLAG_SAMPLER_HEAP_DIRECTLY_INDEXED = 0x800*/
CD3DX12_ROOT_SIGNATURE_DESC RootSignatureDesc(
	1, RootParam, 0, nullptr,D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);

//创建二进制的 根签名
ComPtr<ID3DBlob> SerializeRootSignature;
ComPtr<ID3DBlob> ErrorBlob;
D3D12SerializeRootSignature(
	&RootSignatureDesc,
	D3D_ROOT_SIGNATURE_VERSION_1,
	SerializeRootSignature.GetAddressOf(),
	ErrorBlob.GetAddressOf()
);

if (!ErrorBlob)
{
	Engine_Error("%s", (char*)ErrorBlob->GetBufferPointer());
}
//创建根签名
//nodemask:操作GPU顶点下表,只有一个GPU时,写0:单个GPU
GetD3D12Device()->CreateRootSignature(
	0,
	SerializeRootSignature->GetBufferPointer(),
	SerializeRootSignature->GetBufferSize(),
	IID_PPV_ARGS(&RootSignature)
	);

Shader


//h
#pragma once
#include"Engine/EngineMinimal.h"

class FShader
{
public:
	//InFileName:Shader保存位置
	//InEntryFunName:入口函数名,Shader进入函数顶点名称,相当于Main
	void BuildShader(const wstring& InFileName, const string& InEntryFunName, const string& InShaderVersion);

protected:
	ComPtr<ID3DBlob> ShaderCode;
};


//cpp
#include"Shader.h"

void FShader::BuildShader(const wstring& InFileName, const string& InEntryFunName, const string& InShaderVersion)
{
	ComPtr< ID3DBlob> ErrorBlobMsg;
	D3DCompileFromFile(
		InFileName.c_str(),
		NULL,
		D3D_COMPILE_STANDARD_FILE_INCLUDE,
		InEntryFunName.c_str(),
		InShaderVersion.c_str(),
#if _DEBUG
		D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION
#else
		0
#endif
		, 0, &ShaderCode, &ErrorBlobMsg
	);

	if (!ErrorBlobMsg)
	{
		Engine_Error("%s", (char*)ErrorBlobMsg->GetBufferPointer());
	}
}
h
FShader VShader;
FShader IShader;

/*	LPCSTR SemanticName:着色器输入的签名中与这个元素关联的HLSL语法
	UINT SemanticIndex;//元素语义索引
	DXGI_FORMAT Format;//指向元素顶点格式
	UINT InputSlot;//当前汇编程序的整数值:0-15
	UINT AlignedByteOffset;//可选,顶点到此元素的偏移量
	D3D12_INPUT_CLASSIFICATION InputSlotClass;
	UINT InstanceDataStepRate//默认是0,每个实例绘制的步数
	*/
vector<D3D12_INPUT_ELEMENT_DESC> InputElementDesc;


cpp
//构建Shader
HLSL
VShader.BuildShader(L"../../../Shader/Hello.hlsl","VertexShaderMain","vs_5_0");
IShader.BuildShader(L"../../../Shader/Hello.hlsl", "PixelShaderMain", "vs_5_0");
InputElementDesc = {
	{"Position",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0},
	{"Color",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,12,D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0}
};

HLSL

输入输出点信息(映射到齐次剪裁面)

cbuffer ConstBuffer : register(b0) //b0->b14
{
    float1x4 World;
}

struct MeshVertexIn
{
    float3 Position : POSITIONT;
    float4 Color : COLOR;
};

struct MeshVertexOut
{
    float3 Position : SV_POSITIONT;
    float4 Color : COLOR;
};

MeshVertexOut VertexShaderMain(MeshVertexIn MV)
{
    MeshVertexOut Out;
    //投影到齐次剪裁面
    Out.Position = mul(float4(MV.Position, 1.f), World);
    Out.Color = MV.Color;
    
    return Out;
}

float4 PixelShaderMain(MeshVertexOut MVOut):SV_TARGET
{
    return MVOut.Color;
}

PSO

流水线状态对象

//PSO
D3D12_GRAPHICS_PIPELINE_STATE_DESC GPSDesc;
memset(&GPSDesc, 0, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));//必须初始化为0,否则崩溃

//绑定输入层元素
GPSDesc.InputLayout.NumElements = (UINT)InputElementDesc.size();
GPSDesc.InputLayout.pInputElementDescs = InputElementDesc.data();

//绑定根签名
GPSDesc.pRootSignature = RootSignature.Get();

// 绑定顶点Shader
GPSDesc.VS.BytecodeLength = VShader.GetBufferSize();
GPSDesc.VS.pShaderBytecode = reinterpret_cast<BYTE*>(VShader.GetBufferData());

//绑定像素Shader
GPSDesc.PS.BytecodeLength = PShader.GetBufferSize();
GPSDesc.PS.pShaderBytecode = PShader.GetBufferData();

//配置光栅化
/*	FillMode = D3D12_FILL_MODE_SOLID;//绘制实物(D3D12_FILL_MODE_WIREFRAME:绘制线框)
	CullMode = D3D12_CULL_MODE_BACK;//剔除三角形后的图元(D3D12_CULL_MODE_NONE:不剔除)
	FrontCounterClockwise = FALSE;//FALSE:根据三角形顶点顺时针绘制。TRUE:逆时针绘制
	DepthBias = D3D12_DEFAULT_DEPTH_BIAS;//像素的深度值:0
	DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;//像素最大深度偏差:0.0
	SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;//像素在斜率上的标量
	DepthClipEnable = TRUE;//是否启用距离(深度)裁剪
	MultisampleEnable = FALSE;//true:线性抗锯齿,false:Alpha抗锯齿
	AntialiasedLineEnable = FALSE;//是否开始行抗锯齿
	ForcedSampleCount = 0;//采样强计数,主要用于UAV渲染,有效值:0 1 2 4 8 16. 0:不采用。>0:不要绑定深度模板视图且,禁用深度测试,确保着色器不输出深度
	ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;//表示当前光栅化是否打开
	*/
GPSDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);

//1111...000:1代表采样哪个样本
GPSDesc.SampleMask = UINT_MAX;//混合状态下的视力模板。多重采样最多采样32位样本, UINT_MAX:表示采样所有样本

GPSDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
GPSDesc.NumRenderTargets = 1;

//设置混合
/*
AlphaToCoverageEnable = FALSE;//是否将当前像素作为渲染目标,是否使用当前的Alpha覆盖进行多重采样
IndependentBlendEnable = FALSE;//是否在同步渲染目标中启用独立的审核。FALSE:只使用RenderTarget的0号(一共八个)
*/
GPSDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);


//设置深度模板
/*	BOOL DepthEnable;//启用深度模板测试
	D3D12_DEPTH_WRITE_MASK DepthWriteMask;//对深度模板的属性进行修改
	D3D12_COMPARISON_FUNC DepthFunc;//标识的深度数据和现有的深度的数据进行比较顶点函数
	BOOL StencilEnable;//启用模板测试
	UINT8 StencilReadMask;//模板数据的深度模板缓冲区的识别有关
	UINT8 StencilWriteMask;
	D3D12_DEPTH_STENCILOP_DESC FrontFace;//表面法线朝向的像素,主要将深度测试和模板测试的结果用在对当前法线朝向相机的像素
	D3D12_DEPTH_STENCILOP_DESC BackFace;//背面的像素
*/
GPSDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);

//将引擎其他位置的参数调过来,Render提供接口
GPSDesc.SampleDesc.Count = GetEngine()->GetDXGISampleCount();
GPSDesc.SampleDesc.Quality = GetEngine()->GetDXGISampleQuality();

GPSDesc.RTVFormats[0] = GetEngine()->GetBackBufferFormat();
GPSDesc.DSVFormat = GetEngine()->GetDepthStencilFormat();


HRESULT PR = GetD3D12Device()->CreateGraphicsPipelineState(&GPSDesc, IID_PPV_ARGS(&PSO));
ANALYSIS_HRESULT(PR);

Draw

前面准备好了常量缓冲区、根签名(描述符表)、Shader(.hlsl)、拷贝顶点信息到CPU、GPU缓冲区、PSO(渲染管线绑定对象,如Mesh)

提交绘制命令

//获取常量缓冲区
ID3D12DescriptorHeap* DescriptorHeap[] = { CBVHeap.Get() };
GetGraphicsCommandList()->SetDescriptorHeaps(_countof(DescriptorHeap), DescriptorHeap);

GetGraphicsCommandList()->SetGraphicsRootSignature(RootSignature.Get());//描述表在这里输入到常量缓冲区

// 提交数据
绑定渲染流水线上的输入槽,可以输入装配阶段传入的顶点数据
D3D12_VERTEX_BUFFER_VIEW VBV=GetVertexBufferView();
GetGraphicsCommandList()->IASetVertexBuffers(
	0,//起始插槽0-15	k
	1,//视口号:k+1 k+2 ...k+n-1
	&VBV
);

D3D12_INDEX_BUFFER_VIEW IBV=GetIndexBufferView();
GetGraphicsCommandList()->IASetIndexBuffer(
	&IBV
);

//要绘制的图元:点、线、面
GetGraphicsCommandList()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
GetGraphicsCommandList()->SetGraphicsRootDescriptorTable(0, CBVHeap->GetGPUDescriptorHandleForHeapStart());
//实际绘制
GetGraphicsCommandList()->DrawIndexedInstanced(
	IndexSize,//顶点数量
	1,//绘制的实例
	0,//顶点缓冲区第一个被绘制的索引
	0,//GPU读取索引缓冲区第一个索引的位置
	0//从顶点缓冲区读取每个实例之前添加到每个索引的值
	);

准备相关矩阵

旋转矩阵

\begin{pmatrix} 1 &0 &0 \\ 0& \cos \alpha &\sin \beta \\ 0&-\sin \alpha &\cos \alpha \end{pmatrix}

\begin{pmatrix} \cos \beta &0 &-\sin \beta \\ 0&1 &0 \\ \sin \beta & 0 &\cos \beta \end{pmatrix}

\begin{pmatrix} \cos \gamma &\sin \gamma &0 \\ -\sin \gamma &\cos \gamma &0 \\ 0 & 0 &1 \end{pmatrix}

模型算法:

基本概念:

1.DX中3个点顺时针排序表示面面向摄像机(存放Index数组中,顺时针存放Index)

InAxialSubdivision:轴(纵)向分段数。

InHeightSubdvision:横向分段数。

2.绘制环形(圆形,非球)上的点时,点数=横向分段数+1(多一个点方便程序化生成,相对于头尾点完全重叠)。

3.绘制时优先考虑绘制特殊点(南北极),在程序化绘制中间部分。

4.球坐标转笛卡尔坐标:

DX中,Y和Z轴相反,Y轴朝上

Beta:纵向夹角,θ:横向夹角

x=rsin(Beta)cos(θ)
z=rsin(θ)sin(Beta)
y=r*cos(Beta)

Box:

CBoxMesh* CBoxMesh::CreateMesh(FMeshRenderingData& MeshData, float InWidth, float InHeight, float InDepth)
{
	float HalfWidth=0.5 * InWidth;
	float HalfHeight= 0.5 * InHeight;
	float HalfDepth= 0.5 * InDepth;

	MeshData.VertexData.push_back(FVertex(XMFLOAT3(-HalfWidth,-HalfHeight,-HalfDepth), XMFLOAT4(Colors::White)));
	MeshData.VertexData.push_back(FVertex(XMFLOAT3(-HalfWidth, HalfHeight, -HalfDepth), XMFLOAT4(Colors::AliceBlue)));
	MeshData.VertexData.push_back(FVertex(XMFLOAT3(HalfWidth, HalfHeight, -HalfDepth), XMFLOAT4(Colors::Aqua)));
	MeshData.VertexData.push_back(FVertex(XMFLOAT3(HalfWidth, -HalfHeight, -HalfDepth), XMFLOAT4(Colors::AntiqueWhite)));
	MeshData.VertexData.push_back(FVertex(XMFLOAT3(-HalfWidth, -HalfHeight, HalfDepth), XMFLOAT4(Colors::Azure)));
	MeshData.VertexData.push_back(FVertex(XMFLOAT3(-HalfWidth, HalfHeight, HalfDepth), XMFLOAT4(Colors::Brown)));
	MeshData.VertexData.push_back(FVertex(XMFLOAT3(HalfWidth, HalfHeight, HalfDepth), XMFLOAT4(Colors::Coral)));
	MeshData.VertexData.push_back(FVertex(XMFLOAT3(HalfWidth, -HalfHeight, HalfDepth), XMFLOAT4(Colors::Crimson)));

	//构建索引
	//前
	MeshData.IndexData.push_back(0); MeshData.IndexData.push_back(1); MeshData.IndexData.push_back(2);
	MeshData.IndexData.push_back(0); MeshData.IndexData.push_back(2); MeshData.IndexData.push_back(3);

	//后
	MeshData.IndexData.push_back(4); MeshData.IndexData.push_back(6); MeshData.IndexData.push_back(5);
	MeshData.IndexData.push_back(4); MeshData.IndexData.push_back(7); MeshData.IndexData.push_back(6);

	//左
	MeshData.IndexData.push_back(4); MeshData.IndexData.push_back(5); MeshData.IndexData.push_back(1);
	MeshData.IndexData.push_back(4); MeshData.IndexData.push_back(1); MeshData.IndexData.push_back(0);

	//右
	MeshData.IndexData.push_back(3); MeshData.IndexData.push_back(2); MeshData.IndexData.push_back(6);
	MeshData.IndexData.push_back(3); MeshData.IndexData.push_back(6); MeshData.IndexData.push_back(7);

	//上
	MeshData.IndexData.push_back(1); MeshData.IndexData.push_back(5); MeshData.IndexData.push_back(6);
	MeshData.IndexData.push_back(1); MeshData.IndexData.push_back(6); MeshData.IndexData.push_back(2);//2

	//下
	MeshData.IndexData.push_back(4); MeshData.IndexData.push_back(0); MeshData.IndexData.push_back(3);
	MeshData.IndexData.push_back(4); MeshData.IndexData.push_back(3); MeshData.IndexData.push_back(7);


	CBoxMesh* OutMesh = new CBoxMesh;
	OutMesh->BuildMesh(&MeshData);

	OutMesh->Init();

	return OutMesh;
}

Sphere:

CSphereMesh* CSphereMesh::CreateMesh(FMeshRenderingData& MeshData, float Radius, float InAxialSubdivision, float InHeightSubdvision)
{

	float ThetaValue = XM_2PI / InHeightSubdvision;
	float BetaValue = XM_PI / InAxialSubdivision;
	//Vertex

	//绘制北极
	MeshData.VertexData.push_back(
		FVertex(
			XMFLOAT3(
				0, Radius, 0),
			XMFLOAT4(Colors::Red)));

	//绘制中间、
	for (uint32_t i = 1; i < InAxialSubdivision; ++i)
	{
		float Beta = i * BetaValue;
		for (uint32_t j = 0; j <= InHeightSubdvision ; ++j)//1
		{
			float Theta = j * ThetaValue;
			MeshData.VertexData.push_back(
				FVertex(
					XMFLOAT3(
						Radius * sinf(Beta) * cosf(Theta),
						Radius * cosf(Beta),
						Radius * sinf(Beta) * sinf(Theta)),
					XMFLOAT4(Colors::White)));

			int TopIndex = MeshData.VertexData.size() - 1;
			FVertex& InVertex = MeshData.VertexData[TopIndex];
			//法线
			XMVECTOR Pos = XMLoadFloat3(&InVertex.Position);
			XMStoreFloat3(&InVertex.Normal, XMVector3Normalize(Pos));
			//切线
			InVertex.UTangent.x = -Radius * sinf(Beta) * sinf(Theta);
			InVertex.UTangent.y = 0;
			InVertex.UTangent.z = Radius * sinf(Beta) * cosf(Theta);
		}
	}

	//南极
	MeshData.VertexData.push_back(
		FVertex(
			XMFLOAT3(
				0, -Radius, 0),
			XMFLOAT4(Colors::Red)));

	//Index
	
	//绘制北极
	for (uint16_t j = 0; j <= InHeightSubdvision; ++j)
	{
		MeshData.IndexData.push_back(0);
		MeshData.IndexData.push_back(j + 1);
		MeshData.IndexData.push_back(j);
	};
	//for (uint16_t j = 1; j < InAxialSubdivision; j++)
	//{
	//	MeshData.IndexData.push_back(0);
	//	MeshData.IndexData.push_back(j+1);
	//	MeshData.IndexData.push_back(j);
	//};
	0 8 1
	//MeshData.IndexData.push_back(0);
	//MeshData.IndexData.push_back(1);
	//MeshData.IndexData.push_back(InAxialSubdivision);

	//绘制中间
	float BaseIndex = 1;
	//float VertexCircleNum = InHeightSubdvision;//南北极也算一圈?
	float VertexCircleNum = InHeightSubdvision + 1;//他是InAxialSubdivision?
	for (uint32_t i = 0; i < InAxialSubdivision -2; ++i)// InHeightSubdvision
	{
		for (uint16_t j = 0; j < InHeightSubdvision; ++j)///InAxialSubdivision
		{
			//三角形1
			MeshData.IndexData.push_back(BaseIndex+i*VertexCircleNum+j);
			MeshData.IndexData.push_back(BaseIndex + i * VertexCircleNum + j+1);
			MeshData.IndexData.push_back(BaseIndex + (i+1)*VertexCircleNum + j);

			//三角形2
			MeshData.IndexData.push_back(BaseIndex + (i + 1) * VertexCircleNum + j);
			MeshData.IndexData.push_back(BaseIndex + i * VertexCircleNum + j + 1);
			MeshData.IndexData.push_back(BaseIndex + (i + 1) * VertexCircleNum + j+1);
		}
	}

	//绘制南极
	int SouthBaseIndex = MeshData.VertexData.size() - 1;
	BaseIndex = SouthBaseIndex - VertexCircleNum;
	for (uint16_t j = 0; j <= InHeightSubdvision; ++j)//1
	{
		MeshData.IndexData.push_back(SouthBaseIndex);
		MeshData.IndexData.push_back(BaseIndex +j);
		MeshData.IndexData.push_back(BaseIndex + j + 1);
	};
	/*MeshData.IndexData.push_back(SouthBaseIndex);
	MeshData.IndexData.push_back(BaseIndex + InAxialSubdivision);
	MeshData.IndexData.push_back(BaseIndex + 1);*/

	CSphereMesh* OutMesh = new CSphereMesh;
	OutMesh->BuildMesh(&MeshData);

	OutMesh->Init();

	return OutMesh;
}

Cone:

CConeMesh* CConeMesh::CreateMesh(FMeshRenderingData& MeshData, float InRadius, float InHight, float InAxialSubdivision, float InHeightSubdvision)
{

	//考虑上下底面半径不同
	float RadiusInterval = -InRadius / InAxialSubdivision;

	float HightInterval = InHight / InAxialSubdivision;
	float Beta = XM_2PI / InHeightSubdvision;
	//自上而下添加点Vertex
	MeshData.VertexData.push_back(
		FVertex(
			XMFLOAT3(0, 0.5 * InHight, 0),
			XMFLOAT4(Colors::Red)
		)
	);

	for (uint32_t i = 1; i <= InAxialSubdivision; i++)
	{
		float Radius = -(i * RadiusInterval);
		float Y = 0.5 * InHight - i * HightInterval;
		for (size_t j = 0; j <= InHeightSubdvision; ++j)
		{
			MeshData.VertexData.push_back(
				FVertex(
					XMFLOAT3(Radius * cosf(j * Beta), Y, Radius * sinf(j * Beta)),
					XMFLOAT4(Colors::White)
				)
			);
		}
	}

	//Bottom
	MeshData.VertexData.push_back(
		FVertex(
			XMFLOAT3(0, -0.5 * InHight, 0),
			XMFLOAT4(Colors::Red)
		)
	);

	//Index
	//顶
	for (uint16_t j = 1; j <= InHeightSubdvision+1; ++j)
	{
		MeshData.IndexData.push_back(0);
		MeshData.IndexData.push_back(j+1);
		MeshData.IndexData.push_back(j);
	}

	float VertexCircleNum = InHeightSubdvision + 1;
	for (uint32_t i = 0; i < InAxialSubdivision-1; i++)
	{
		for (uint16_t j = 1; j <= InHeightSubdvision; ++j)
		{
			//三角形1
			MeshData.IndexData.push_back((i + 1) * VertexCircleNum + j + 1);
			MeshData.IndexData.push_back((i + 1) * VertexCircleNum + j);
			MeshData.IndexData.push_back(i * VertexCircleNum + j);


			//三角形2

			MeshData.IndexData.push_back(i * VertexCircleNum + j + 1);
			MeshData.IndexData.push_back((i + 1) * VertexCircleNum + j + 1);
			MeshData.IndexData.push_back(i * VertexCircleNum + j);
		}
	}

	float Bottom = MeshData.VertexData.size() - 1;
	float BaseIndex = Bottom - VertexCircleNum;
	for (uint16_t j = 0; j <= InHeightSubdvision; ++j)
	{
		MeshData.IndexData.push_back(Bottom);
		MeshData.IndexData.push_back(BaseIndex+j);
		MeshData.IndexData.push_back(BaseIndex+j+1);

	}

	CConeMesh* OutMesh = new CConeMesh;
	OutMesh->BuildMesh(&MeshData);

	OutMesh->Init();

	return OutMesh;
}

Cylinder:

CCylinderMesh* CCylinderMesh::CreateMesh(FMeshRenderingData& MeshData, float InTopRadius, float InBottomRadius,float InHight, float InAxialSubdivision, float InHeightSubdvision)
{

	//考虑上下底面半径不同
	float RadiuInterval = (InTopRadius - InBottomRadius) / InAxialSubdivision;

	float HightInterval = InHight / InAxialSubdivision;
	float Beta = XM_2PI / InHeightSubdvision;
	//自上而下添加点Vertex
	顶部
	MeshData.VertexData.push_back(
		FVertex(
			XMFLOAT3(0, 0.5 * InHight, 0),
			XMFLOAT4(Colors::Red)
		)
	);
	/*for (size_t j = 0; j < InAxialSubdivision; ++j)
	{
		float Radius = InTopRadius;
		MeshData.VertexData.push_back(
			FVertex(
				XMFLOAT3(Radius * cosf(j * Beta), 0.5 * InHight, Radius * sinf(j * Beta)),
				XMFLOAT4(Colors::White)
			)
		);
	};*/

	中部
	for (uint32_t i = 0; i <= InAxialSubdivision; i++)//<x-1
	{
		float Y = 0.5 * InHight - i * HightInterval;
		float Radius = InTopRadius - i * RadiuInterval;

		for (size_t j = 0; j < InHeightSubdvision+1; ++j)//<X+1
		{
			MeshData.VertexData.push_back(
				FVertex(
					XMFLOAT3(Radius * cosf(j * Beta), Y, Radius * sinf(j * Beta)),
					XMFLOAT4(Colors::White)
				)
			);
		};
	}

	底部
	/*for (size_t j = 0; j < InAxialSubdivision; ++j)
	{
		float Radius = InBottomRadius;
		MeshData.VertexData.push_back(
			FVertex(
				XMFLOAT3(Radius * cosf(j * Beta), -0.5 * InHight, Radius * sinf(j * Beta)),
				XMFLOAT4(Colors::White)
			)
		);
	};*/
	MeshData.VertexData.push_back(
		FVertex(
			XMFLOAT3(0, -0.5 * InHight, 0),
			XMFLOAT4(Colors::Red)
		)
	);

	//绘制Index
	// 
	// 绘制顶部
	for (uint16_t j = 0; j < InHeightSubdvision; ++j)///InAxialSubdivision
	{
		MeshData.IndexData.push_back(0);
		MeshData.IndexData.push_back(j+1);
		MeshData.IndexData.push_back(j);
	}
	//绘制中间
	float BaseIndex = 1;
	//float VertexCircleNum = InHeightSubdvision;//南北极也算一圈?
	float VertexCircleNum = InHeightSubdvision + 1;//他是InAxialSubdivision?
	for (uint32_t i = 0; i < InAxialSubdivision ; i++)// InHeightSubdvision
	{
		for (uint16_t j = 1; j <= InHeightSubdvision; ++j)///InAxialSubdivision
		{
			//反向,法线远离摄像机
			三角形1
			//MeshData.IndexData.push_back(i * VertexCircleNum + j);
			//MeshData.IndexData.push_back((i + 1) * VertexCircleNum + j);
			//MeshData.IndexData.push_back((i + 1) * VertexCircleNum + j + 1);

			三角形2
			//MeshData.IndexData.push_back(i * VertexCircleNum + j);
			//MeshData.IndexData.push_back((i + 1) * VertexCircleNum + j+1);
			//MeshData.IndexData.push_back(i * VertexCircleNum + j + 1);

			//正向,法线朝向摄像机
			//三角形1
			MeshData.IndexData.push_back((i + 1) * VertexCircleNum + j + 1);
			MeshData.IndexData.push_back((i + 1) * VertexCircleNum + j);
			MeshData.IndexData.push_back(i * VertexCircleNum + j);
			
			
			//三角形2
			
			MeshData.IndexData.push_back(i * VertexCircleNum + j + 1);
			MeshData.IndexData.push_back((i + 1) * VertexCircleNum + j + 1);
			MeshData.IndexData.push_back(i * VertexCircleNum + j);
			
		}
	}

	// 绘制底部
	float Bottom = MeshData.VertexData.size() - 1;
	BaseIndex = Bottom - VertexCircleNum;
	for (uint16_t j = 0; j < InHeightSubdvision; j++)///InAxialSubdivision
	{
		MeshData.IndexData.push_back(Bottom);
		MeshData.IndexData.push_back(BaseIndex+j);
		MeshData.IndexData.push_back(BaseIndex+j+1);
	}

	CCylinderMesh* OutMesh = new CCylinderMesh;
	OutMesh->BuildMesh(&MeshData);

	OutMesh->Init();

	return OutMesh;
}

PlaneMesh:

CPlaneMesh* CPlaneMesh::CreateMesh(FMeshRenderingData& MeshData, float InWidth, float InHeight,  uint32_t InHeightSubdvision, uint32_t InAxialSubdivision )
{
	float HalfWidth = 0.5 * InWidth;
	float HalfHeight = 0.5 * InHeight;

	float WidthInterval = InWidth / InAxialSubdivision;
	float HightInterval = InHeight / InHeightSubdvision;

	//Vertex
	for (uint32_t i = 0; i < InAxialSubdivision+1; i++)
	{
		float X = HalfWidth - i * WidthInterval;
		for (uint32_t j = 0; j < InHeightSubdvision +1; j++)
		{
			float Z = HalfHeight - j * HightInterval;
			MeshData.VertexData.push_back(
				FVertex(
					XMFLOAT3(X, 0, Z),
					XMFLOAT4(Colors::AliceBlue)
				)
			);
		}
	}

	//Index
	float VertexCircleNum = InHeightSubdvision + 1;
	for (uint32_t i = 0; i < InAxialSubdivision ; i++)
	{
		for (uint32_t j = 0; j < InHeightSubdvision; j++)
		{
			//三角形1
			MeshData.IndexData.push_back((i + 1) * VertexCircleNum + j + 1);
			MeshData.IndexData.push_back((i + 1) * VertexCircleNum + j);
			MeshData.IndexData.push_back(i * VertexCircleNum + j);


			//三角形2

			MeshData.IndexData.push_back(i * VertexCircleNum + j + 1);
			MeshData.IndexData.push_back((i + 1) * VertexCircleNum + j + 1);
			MeshData.IndexData.push_back(i * VertexCircleNum + j);
		}
	}

	
	CPlaneMesh* OutMesh = new CPlaneMesh;
	OutMesh->BuildMesh(&MeshData);

	OutMesh->Init();

	return OutMesh;
}

Custom(Object):

CCustomMesh* CCustomMesh::CreateMesh(FMeshRenderingData& MeshData, string& InPath)
{
	{
		unsigned int FileSize = get_file_size_by_filename(InPath.c_str());

		char* Buff = new char[FileSize+1];
		memset(Buff, 0, FileSize+1);
		get_file_buf(InPath.c_str(), Buff);

		if (!LoadObjectFromBuff(Buff, FileSize, MeshData))
		{

		}
		delete Buff;
	}


	CCustomMesh* OutMesh = new CCustomMesh;
	OutMesh->BuildMesh(&MeshData);

	OutMesh->Init();

	return OutMesh;
}

bool CCustomMesh::LoadObjectFromBuff(char* InBuff, uint32_t InBuffSize, FMeshRenderingData& MeshData)
{
	if (InBuffSize>0)
	{
		stringstream BuffStream(InBuff);
		char TmpLine[256] = { 0 };
		string MidTmpTag;
		for (; !BuffStream.eof();)
		{
			memset(TmpLine, 0, 256);

			//读取一行数据
			BuffStream.getline(TmpLine,256);
			if (strlen(TmpLine) > 0)
			{
				//Vertex
				if (TmpLine[0] == 'v')
				{
					stringstream TmpStream(TmpLine);
					TmpStream >> MidTmpTag;
					if (TmpLine[1] == 'n')
					{

					}
					else if (TmpLine[1] == 't')
					{

					}
					else
					{
						//先添加一个
						MeshData.VertexData.push_back(
							FVertex(
								XMFLOAT3(),
								XMFLOAT4(Colors::White)));

						//拿到点的位置
						size_t Top = MeshData.VertexData.size() - 1;
						XMFLOAT3& Float3InPos= MeshData.VertexData[Top].Position;

						//解析位置
						TmpStream >> Float3InPos.x;
						TmpStream >> Float3InPos.y;
						TmpStream >> Float3InPos.z;
					}
				}
				//Index	绘制指令  
					362/380/361	363/381/363 382/342/382  A/B/C A:顶点索引	B:纹理索引	C:法线索引

				else if (TmpLine[0] == 'f')
				{
					stringstream TmpStream(TmpLine);
					TmpStream >> MidTmpTag;

					char SaveLineString[256] = {0};
					char TmpBuff[256] = { 0 };

					for (size_t i = 0; i < 3; i++)
					{
						memset(SaveLineString, 0, 256);

						//输入一行
						TmpStream >> SaveLineString;
						//找到索引位置,拷贝
						int StringPosA = find_string(SaveLineString, "/", 0);
						memset(TmpBuff, 0, 256);
						char* VPosIndex = string_mid(SaveLineString, TmpBuff, 0, StringPosA);

						MeshData.IndexData.push_back(atoi(VPosIndex));

						//纹理坐标
						int StringPosB = find_string(SaveLineString, "/", StringPosA+1);
						memset(TmpBuff, 0, 256);
						char* MPosIndex = string_mid(SaveLineString, TmpBuff, StringPosA + 1, StringPosB- StringPosA-1);

						//法线索引
						memset(TmpBuff, 0, 256);
						char* NPosIndex = string_mid(SaveLineString, TmpBuff, StringPosB + 1, strlen(SaveLineString)-StringPosB-1);
					}
				}
			}
			
		}
	}
	return true;
}

TBN矩阵

tangant轴(T)、bitangent轴(B)、轴(法线)(N),即切线空间(TBN)

基本概念:

1.\vec{a}\cdot \vec{b}的意义:一是表示角度二是a投影到b的 长度

2.T B相当于U V

一个三角形的三个点A\left ( X_{a},Y_{a},Z_{a} \right ) B\left ( X_{b},Y_{b},Z_{b} \right ) C\left ( X_{c},Y_{c},Z_{c} \right )

e_{1}=C-B        e_{2}=A-B

(U、V )

\bigtriangleup U_{1}=U_{2}-U_{1}

\bigtriangleup V_{1}=V_{2}-V_{1}

\bigtriangleup U_{2}=U_{3}-U_{2}

\bigtriangleup V_{2}=V_{3}-V_{2}

向量和T B的关系

e_{1}=\bigtriangleup U_{1}\cdot T+\bigtriangleup V_{1}\cdot B

e_{2}=\bigtriangleup U_{2}\cdot T+\bigtriangleup V_{2}\cdot B

用矩阵表示

\begin{pmatrix} e_{1}\\ e_{1} \end{pmatrix}=\begin{pmatrix} \Delta U_{1} &\Delta V_{1} \\ \Delta U_{2} &\Delta V_{2} \end{pmatrix}\cdot \begin{pmatrix} T\\ B \end{pmatrix}

反求T B(也就是我需要的UV)

根据矩阵乘法A^{-1}=\frac{1}{\left | A \right |}\cdot A^{*}

\begin{pmatrix} \Delta U_{1} &\Delta V_{1} \\ \Delta U_{2} &\Delta V_{2} \end{pmatrix}^{-1}\cdot \begin{pmatrix} e_{1}\\ e_{1} \end{pmatrix}= \begin{pmatrix} T\\ B \end{pmatrix}

展开

\begin{pmatrix} T_{x} &T_{y} &T_{z} \\ B_{x}& B_{y} & B_{z} \end{pmatrix}=\frac{1}{\left | A \right |}\cdot A^{*}\cdot \begin{pmatrix} e_{1x} &e_{1y} &e_{1z} \\ e_{2x}& e_{2y} & e_{2z} \end{pmatrix}

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
应用背景为变电站电力巡检,基于YOLO v4算法模型对常见电力巡检目标进行检测,并充分利用Ascend310提供的DVPP等硬件支持能力来完成流媒体的传输、处理等任务,并对系统性能做出一定的优化。.zip深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值