<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>风牛菜籽 &#187; 优化</title>
	<atom:link href="http://www.caiyanpei.com/tag/%e4%bc%98%e5%8c%96/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.caiyanpei.com</link>
	<description>拖延症重症患者</description>
	<lastBuildDate>Tue, 25 Mar 2025 01:51:19 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.6.1</generator>
		<item>
		<title>C++客户端使用RenderDoc和Visual Studio截帧工具调优</title>
		<link>http://www.caiyanpei.com/c_renderdoc_visual-studio_opt/</link>
		<comments>http://www.caiyanpei.com/c_renderdoc_visual-studio_opt/#comments</comments>
		<pubDate>Mon, 25 Dec 2023 13:44:09 +0000</pubDate>
		<dc:creator>tsai</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[调优]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[性能分析]]></category>

		<guid isPermaLink="false">http://www.caiyanpei.com/?p=651</guid>
		<description><![CDATA[在C++游戏客户端开发中，经常会碰到渲染性能优化各种头疼的问题。为了分析渲染问题 &#8230; <a href="http://www.caiyanpei.com/c_renderdoc_visual-studio_opt/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>在C++游戏客户端开发中，经常会碰到渲染性能优化各种头疼的问题。为了分析渲染问题并找到性能瓶颈，可以借助截帧工具，如<strong>RenderDoc或</strong><strong>Visual Studio自带的截帧工具</strong>。本文探讨使用这两种工具进行调试和优化，尝试提升开发中客户端的渲染性能。</p>
<hr />
<h1>一、为什么需要截帧工具？</h1>
<p>在游戏开发中，渲染性能问题往往表现为帧率下降、卡顿或画面异常。通过截帧工具，我们可以：</p>
<ol>
<li>​<strong>分析每一帧的渲染过程</strong>：查看Draw Call、渲染状态、资源使用情况等。</li>
<li>​<strong>定位性能瓶颈</strong>：找到渲染性能问题的根源，如过多的Draw Call、高复杂度的Shader、不合理的资源使用等。</li>
<li>​<strong>验证优化效果</strong>：通过对比优化前后的截帧数据，验证优化策略的有效性。</li>
</ol>
<hr />
<h1>二、RenderDoc的使用</h1>
<p>RenderDoc是一款开源的图形调试工具，支持DirectX、OpenGL、Vulkan等多种图形API。以下是使用RenderDoc优化C++游戏客户端的步骤：</p>
<h2>1. ​<strong>安装与配置</strong></h2>
<ul>
<li>下载并安装RenderDoc：<a title="RenderDoc官网" href="https://renderdoc.org/" target="_blank">RenderDoc官网</a></li>
<li>启动RenderDoc，配置游戏客户端的可执行文件路径和启动参数。</li>
</ul>
<h2>2. ​<strong>捕获帧数据</strong></h2>
<ul>
<li>在RenderDoc中点击“Launch”启动游戏客户端。</li>
<li>在游戏中运行到需要调试的场景，按下<code>F12</code>（默认快捷键）捕获当前帧。</li>
<li>捕获完成后，RenderDoc会自动加载帧数据。</li>
</ul>
<h2>3. ​<strong>分析帧数据</strong></h2>
<ul>
<li>​<strong>Draw Call分析</strong>：查看每一帧的Draw Call数量，找出过多的Draw Call或重复的渲染操作。</li>
<li>​<strong>资源查看</strong>：检查纹理、缓冲区等资源的使用情况，确保资源加载和释放合理。</li>
<li>​<strong>Shader调试</strong>：查看Shader的输入输出，分析Shader的性能问题。</li>
<li>​<strong>渲染状态</strong>：检查深度测试、混合模式等渲染状态，确保设置正确。</li>
</ul>
<h2>4. ​<strong>优化建议</strong></h2>
<ul>
<li>​<strong>减少Draw Call</strong>：使用批处理（Batching）或实例化（Instancing）减少Draw Call数量。</li>
<li>​<strong>优化Shader</strong>：简化Shader计算，减少纹理采样次数。</li>
<li>​<strong>合理使用资源</strong>：压缩纹理格式，减少显存占用。</li>
</ul>
<hr />
<h1>三、Visual Studio截帧工具的使用指南</h1>
<p>Visual Studio自带的截帧工具（Graphics Debugger）是DirectX开发的强大调试工具，以下是使用步骤：</p>
<h2>1. ​<strong>启用Graphics Debugger</strong></h2>
<ul>
<li>在Visual Studio中打开游戏客户端项目。</li>
<li>点击“调试”菜单，选择“Graphics &gt; Start Graphics Debugging”。</li>
</ul>
<h2>2. ​<strong>捕获帧数据</strong></h2>
<ul>
<li>游戏启动后，运行到需要调试的场景。</li>
<li>在Visual Studio中点击“Graphics &gt; Capture Frame”捕获当前帧。</li>
</ul>
<h2>3. ​<strong>分析帧数据</strong></h2>
<ul>
<li>​<strong>事件列表</strong>：查看每一帧的渲染事件，分析Draw Call和渲染状态。</li>
<li>​<strong>资源查看</strong>：检查纹理、缓冲区等资源的使用情况。</li>
<li>​<strong>Pipeline状态</strong>：查看顶点着色器、像素着色器等阶段的输入输出。</li>
<li>​<strong>帧性能分析</strong>：使用“Frame Analysis”工具分析每一帧的性能瓶颈。</li>
</ul>
<h2>4. ​<strong>优化建议</strong></h2>
<ul>
<li>​<strong>减少渲染状态切换</strong>：合并相同渲染状态的Draw Call。</li>
<li>​<strong>优化资源使用</strong>：使用Mipmaps、压缩纹理格式。</li>
<li>​<strong>Shader优化</strong>：减少复杂计算，使用低精度数据类型。</li>
</ul>
<hr />
<h1>四、常见优化点</h1>
<h2>1：Draw Call过多</h2>
<ul>
<li>​<strong>问题描述</strong>：游戏帧率下降，RenderDoc显示Draw Call数量过多。</li>
<li>​<strong>可能解决方案</strong>：
<ol>
<li>使用批处理（Batching）合并相同材质的物体。</li>
<li>使用实例化（Instancing）渲染大量相同的物体。</li>
</ol>
</li>
<li>​<strong>验证效果</strong>：RenderDoc显示Draw Call数量显著减少，帧率提升。</li>
</ul>
<h2>2：Shader性能瓶颈</h2>
<ul>
<li>​<strong>问题描述</strong>：Visual Studio截帧工具显示像素着色器耗时较高。</li>
<li>​<strong>可能解决方案</strong>：
<ol>
<li>简化Shader计算，减少纹理采样次数。</li>
<li>使用低精度数据类型（如<code>half</code>代替<code>float</code>）。</li>
</ol>
</li>
<li>​<strong>验证效果</strong>：Visual Studio帧性能分析显示像素着色器耗时降低。</li>
</ul>
<h2>3：纹理资源过大</h2>
<ul>
<li>​<strong>问题描述</strong>：RenderDoc显示纹理资源占用显存过高。</li>
<li>​<strong>可能解决方案</strong>：
<ol>
<li>压缩纹理格式（如BC7、ASTC）。</li>
<li>使用Mipmaps优化远处纹理的渲染。</li>
</ol>
</li>
<li>​<strong>验证效果</strong>：RenderDoc显示显存占用显著减少。</li>
</ul>
<hr />
<h1>五、工具对比与选择</h1>
<div>
<table>
<thead>
<tr>
<th>工具</th>
<th>优点</th>
<th>缺点</th>
<th>适用场景</th>
</tr>
</thead>
<tbody>
<tr>
<td>​<strong>RenderDoc</strong></td>
<td>跨平台，支持多种图形API，功能强大</td>
<td>需要单独安装，学习曲线较陡</td>
<td>跨平台开发，深度调试</td>
</tr>
<tr>
<td>​<strong>Visual Studio</strong></td>
<td>集成开发环境，与C++项目无缝衔接</td>
<td>仅支持DirectX，功能相对有限</td>
<td>DirectX开发，快速调试</td>
</tr>
</tbody>
</table>
</div>
<p><strong>选择建议</strong>：</p>
<ul>
<li>如果需要跨平台支持或深度调试，选择RenderDoc。</li>
<li>如果是DirectX开发且追求快速调试，选择Visual Studio。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.caiyanpei.com/c_renderdoc_visual-studio_opt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unity Shader优化策略：提升性能与效果的关键</title>
		<link>http://www.caiyanpei.com/unity-shader-optimized/</link>
		<comments>http://www.caiyanpei.com/unity-shader-optimized/#comments</comments>
		<pubDate>Sat, 12 Nov 2022 13:25:40 +0000</pubDate>
		<dc:creator>tsai</dc:creator>
				<category><![CDATA[Unity]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[shader]]></category>
		<category><![CDATA[unity]]></category>
		<category><![CDATA[优化]]></category>

		<guid isPermaLink="false">http://www.caiyanpei.com/?p=647</guid>
		<description><![CDATA[在Unity开发中，Shader是渲染效果的核心，但复杂的Shader往往会带来 &#8230; <a href="http://www.caiyanpei.com/unity-shader-optimized/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>在Unity开发中，Shader是渲染效果的核心，但复杂的Shader往往会带来性能问题。为了在保证视觉效果的同时提升性能，Shader优化成为了我们平常必须要理解应用的一环。本文主要探讨Unity中Shader优化的策略。</p>
<hr />
<h1>一、Shader优化的重要性</h1>
<p>Shader是GPU执行的程序，负责计算每个像素的颜色和光照效果。复杂的Shader会导致以下问题：</p>
<ul>
<li>​<strong>GPU负载过高</strong>：帧率下降，游戏卡顿。</li>
<li>​<strong>发热和耗电</strong>：移动设备性能瓶颈。</li>
<li>​<strong>渲染效率低</strong>：影响整体游戏体验。</li>
</ul>
<p>因此，Shader优化不仅是提升性能的关键，也是保证游戏流畅运行的必要手段。</p>
<hr />
<h1>二、Shader优化的核心策略</h1>
<h2>1. ​<strong>减少计算复杂度</strong></h2>
<ul>
<li>​<strong>避免不必要的计算</strong>：在Shader中只计算真正需要的值。例如，如果不需要法线贴图，就不要计算法线相关的值。</li>
<li>​<strong>简化数学运算</strong>：使用低精度的数据类型（如<code>half</code>代替<code>float</code>），减少复杂的数学运算（如<code>pow</code>、<code>sin</code>、<code>cos</code>等）。</li>
<li>​<strong>分支优化</strong>：尽量避免在Shader中使用<code>if</code>语句，因为GPU对分支处理效率较低。可以使用<code>step</code>或<code>lerp</code>等函数替代。</li>
</ul>
<p>​<strong>示例：​</strong></p>
<pre><code>// 不推荐
if (value &gt; 0.5) {
    color = red;
} else {
    color = blue;
}

// 推荐
color = lerp(blue, red, step(0.5, value));</code></pre>
<h2>2. ​<strong>优化纹理采样</strong></h2>
<ul>
<li>​<strong>减少纹理采样次数</strong>：每次纹理采样都会消耗性能，尽量减少采样次数。例如，将多个纹理合并为一张纹理（纹理图集）。</li>
<li>​<strong>使用Mipmaps</strong>：启用Mipmaps可以减少远处纹理的采样复杂度，提升性能。</li>
<li>​<strong>优化纹理格式</strong>：根据需求选择合适的纹理格式（如ETC2、ASTC），减少显存占用。</li>
</ul>
<p>​<strong>示例：​</strong></p>
<pre><code>// 不推荐
float4 color1 = tex2D(_MainTex, uv1);
float4 color2 = tex2D(_DetailTex, uv2);

// 推荐
float4 color = tex2D(_CombinedTex, uv);</code></pre>
<h2>3. ​<strong>优化光照计算</strong></h2>
<ul>
<li>​<strong>使用简化光照模型</strong>：在移动设备上，可以使用Lambert或Blinn-Phong等简化光照模型，而不是复杂的PBR模型。</li>
<li>​<strong>烘焙光照</strong>：将静态物体的光照信息烘焙到光照贴图中，减少实时计算。</li>
<li>​<strong>减少实时光源</strong>：尽量减少场景中的实时光源数量，使用点光源或聚光灯替代平行光。</li>
</ul>
<p>​<strong>示例：​</strong></p>
<pre><code>// 不推荐（复杂PBR）
float3 brdf = CalculateBRDF(normal, viewDir, lightDir);

// 推荐（简化Blinn-Phong）
float3 diffuse = max(dot(normal, lightDir), 0.0) * _LightColor;
float3 specular = pow(max(dot(reflectDir, viewDir), 0.0), _Gloss) * _SpecularColor;</code></pre>
<h2>4. ​<strong>减少顶点着色器计算</strong></h2>
<ul>
<li>​<strong>将计算移到片段着色器</strong>：如果某些计算在顶点着色器和片段着色器中重复，可以将它们移到片段着色器中，减少顶点着色器的负载。</li>
<li>​<strong>优化顶点数据</strong>：减少顶点数据的数量，例如使用压缩的顶点格式。</li>
</ul>
<p>​<strong>示例：​</strong></p>
<pre><code>// 不推荐（在顶点着色器中计算光照）
v2f vert(appdata v) {
    v2f o;
    o.worldPos = mul(unity_ObjectToWorld, v.vertex);
    o.normal = UnityObjectToWorldNormal(v.normal);
    o.lightDir = normalize(_WorldSpaceLightPos0.xyz - o.worldPos);
    return o;
}

// 推荐（在片段着色器中计算光照）
v2f vert(appdata v) {
    v2f o;
    o.worldPos = mul(unity_ObjectToWorld, v.vertex);
    o.normal = UnityObjectToWorldNormal(v.normal);
    return o;
}</code></pre>
<h2>5. ​<strong>使用Shader变体</strong></h2>
<ul>
<li>​<strong>减少变体数量</strong>：使用<code>#pragma multi_compile</code>或<code>#pragma shader_feature</code>生成多个Shader变体，避免不必要的功能启用。</li>
<li>​<strong>剔除无用变体</strong>：在Shader中根据平台或功能需求，剔除无用的变体。</li>
</ul>
<p>​<strong>示例：​</strong></p>
<pre><code>#pragma multi_compile _ _USE_DETAIL
#ifdef _USE_DETAIL
    float4 detailColor = tex2D(_DetailTex, uv);
    color *= detailColor;
#endif</code></pre>
<h2>6. ​<strong>使用GPU Instancing</strong></h2>
<ul>
<li>​<strong>减少Draw Call</strong>：对于大量相同的物体，使用GPU Instancing可以减少Draw Call，提升性能。</li>
<li>​<strong>优化材质设置</strong>：启用<code>Enable GPU Instancing</code>选项，确保材质支持实例化。</li>
</ul>
<p>​<strong>示例：​</strong></p>
<pre><code>#pragma multi_compile_instancing
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
UNITY_INSTANCING_BUFFER_END(Props)</code></pre>
<hr />
<h1>三、工具与调试</h1>
<h2>1. ​<strong>Frame Debugger</strong></h2>
<ul>
<li>使用Unity的Frame Debugger分析每一帧的渲染过程，找出性能瓶颈。</li>
</ul>
<h2>2. ​<strong>Shader性能分析</strong></h2>
<ul>
<li>使用工具（如RenderDoc、Xcode GPU Frame Capture）分析Shader的性能。</li>
</ul>
<h2>3. ​<strong>Profiler</strong></h2>
<ul>
<li>使用Unity Profiler监控GPU和CPU的负载，定位性能问题。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.caiyanpei.com/unity-shader-optimized/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>unity帧率优化</title>
		<link>http://www.caiyanpei.com/unity%e5%b8%a7%e7%8e%87%e4%bc%98%e5%8c%96/</link>
		<comments>http://www.caiyanpei.com/unity%e5%b8%a7%e7%8e%87%e4%bc%98%e5%8c%96/#comments</comments>
		<pubDate>Tue, 06 Jun 2017 12:41:13 +0000</pubDate>
		<dc:creator>tsai</dc:creator>
				<category><![CDATA[Unity]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[日志]]></category>
		<category><![CDATA[unity]]></category>
		<category><![CDATA[优化]]></category>

		<guid isPermaLink="false">http://www.caiyanpei.com/?p=586</guid>
		<description><![CDATA[在Unity中，帧率（Frame Rate）是指每秒钟渲染的帧数，常用单位为FP &#8230; <a href="http://www.caiyanpei.com/unity%e5%b8%a7%e7%8e%87%e4%bc%98%e5%8c%96/">继续阅读 <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>在Unity中，帧率（Frame Rate）是指每秒钟渲染的帧数，常用单位为FPS（Frames Per Second）。游戏开发过程中，如果帧率低了，可能就是受到以下因素的影响：</p>
<p>1. 渲染时间：每帧的渲染时间取决于场景中的物体数量、复杂度以及使用的特效和着色器等。渲染时间过长会导致帧率下降。</p>
<p>2. CPU性能：CPU负责执行游戏逻辑、物理模拟、AI计算等任务。如果CPU性能不足，可能无法在每帧的时间限制内完成必要的计算，导致帧率下降。</p>
<p>3. GPU性能：GPU负责处理图形渲染任务。如果GPU性能不足，无法及时处理渲染指令，导致帧率下降。</p>
<p>4. 游戏逻辑复杂度：复杂的游戏逻辑、AI计算、碰撞检测等任务会消耗CPU的计算资源，影响帧率。</p>
<p>帧率对游戏的运行流畅度有重要影响。较高的帧率能够提供更流畅的动画和交互体验，而较低的帧率可能导致卡顿、延迟响应和不流畅的动画效果。</p>
<p>几个可考优化方案：</p>
<p>1. 减少渲染开销：通过减少复杂的特效、减少细节或使用合理的LOD系统来减少渲染负载，从而提高帧率。</p>
<p>2. 优化代码性能：通过优化游戏逻辑、减少资源加载和销毁、使用对象池等技术来减少CPU计算开销。</p>
<p>3. 使用批处理技术：通过合并渲染操作，减少Draw Call的数量，从而提高GPU性能。</p>
<p>4. 适当使用线程：将耗时的计算任务放在单独的线程中执行，避免阻塞主线程，提高CPU利用率。</p>
<p>5. 使用合理的资源管理：合理使用纹理压缩、资源压缩和内存优化技术，减少内存占用和加载时间。</p>
<p>6. 避免过度渲染：根据场景需要，避免无意义的渲染操作，如遮挡物体、避免渲染在屏幕外的物体等。</p>
<p>7. 使用性能分析工具：利用Unity提供的性能分析工具，如Profiler，可以定位性能瓶颈并进行针对性的优化。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caiyanpei.com/unity%e5%b8%a7%e7%8e%87%e4%bc%98%e5%8c%96/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
