Files
lwjglbook-CN-Translation/24-hud-revisited/index.html
2024-07-17 21:58:59 +08:00

347 lines
18 KiB
HTML
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="author" content="Mouse0w0" />
<link rel="shortcut icon" href="../img/favicon.ico" />
<title>回顾HUD - NanoVG - Lwjglbook中文翻译</title>
<link rel="stylesheet" href="../css/theme.css" />
<link rel="stylesheet" href="../css/theme_extra.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github.min.css" />
<script>
// Current page data
var mkdocs_page_name = "\u56de\u987eHUD - NanoVG";
var mkdocs_page_input_path = "24-hud-revisited.md";
var mkdocs_page_url = null;
</script>
<!--[if lt IE 9]>
<script src="../js/html5shiv.min.js"></script>
<![endif]-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href=".." class="icon icon-home"> Lwjglbook中文翻译
</a><div role="search">
<form id ="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" title="Type search term here" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<ul>
<li class="toctree-l1"><a class="reference internal" href="../01-first-steps/">事前准备</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../02-the-game-loop/">游戏循环</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../03-a-brief-about-coordinates/">坐标简介</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../04-rendering/">渲染</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../05-more-on-rendering/">渲染补充</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../06-transformations/">变换</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../07-textures/">纹理</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../08-camera/">摄像机</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../09-loading-more-complex-models/">加载更复杂的模型</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../10-let-there-be-light/">要有光</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../11-let-there-be-even-more-light/">要有更多的光</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../12-game-hud/">游戏HUD</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../13-sky-box-and-some-optimizations/">天空盒与一些优化</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../14-height-maps/">高度图</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../15-terrain-collisions/">地形碰撞</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../16-fog/"></a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../17-normal-mapping/">法线贴图</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../18-shadows/">阴影</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../19-animations/">动画</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../20-particles/">粒子</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../21-instanced-rendering/">实例化渲染</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../22-audio/">音效</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../23-3d-object-picking/">三维物体选取</a>
</li>
</ul>
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal current" href="#">回顾HUD - NanoVG</a>
<ul class="current">
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../25-optimizations-frustum-culling/">优化 - 截锥剔除</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../26-cascaded-shadow-maps/">级联阴影映射</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../27-assimp/">Assimp库</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../28-deferred-shading/">延迟着色法</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../a01-opengl-debugging/">附录 A - OpenGL调试</a>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../glossary/">术语表</a>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="Mobile navigation menu">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="..">Lwjglbook中文翻译</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content"><div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href=".." class="icon icon-home" aria-label="Docs"></a></li>
<li class="breadcrumb-item active">回顾HUD - NanoVG</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/Mouse0w0/lwjglbook-CN-Translation/edit/master/docs/24-hud-revisited.md" class="icon icon-github"> Edit on GitHub</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div class="section" itemprop="articleBody">
<h1 id="hud-nanovghud-revisited-nanovg">回顾HUD - NanoVGHUD Revisited - NanoVG</h1>
<p>在此前的章节中我们讲解了如何使用正交投影在场景顶部创建一个HUD以渲染图形和纹理。在本章中我们将学习如何使用<a href="https://github.com/memononen/nanovg">NanoVG</a>库来渲染抗锯齿矢量图形从而以简单的方式创建更复杂的HUD。</p>
<p>你可以使用许多其他库来完成此事,例如<a href="https://github.com/nifty-gui/nifty-gui">Nifty GUI</a><a href="https://github.com/vurtun/nuklear">Nuklear</a>等。在本章是我们将重点介绍NanoVG因为它使用起来非常简单但是如果你希望开发可与按钮、菜单和窗口交互的复杂GUI那你可能需要的是<a href="https://github.com/nifty-gui/nifty-gui">Nifty GUI</a></p>
<p>使用<a href="https://github.com/memononen/nanovg">NanoVG</a>首先是要在<code>pom.xml</code>文件中添加依赖项(一个是用于编译时所需的依赖项,另一个是用于运行时所需的本地代码):</p>
<pre><code class="language-xml">...
&lt;dependency&gt;
&lt;groupId&gt;org.lwjgl&lt;/groupId&gt;
&lt;artifactId&gt;lwjgl-nanovg&lt;/artifactId&gt;
&lt;version&gt;${lwjgl.version}&lt;/version&gt;
&lt;/dependency&gt;
...
&lt;dependency&gt;
&lt;groupId&gt;org.lwjgl&lt;/groupId&gt;
&lt;artifactId&gt;lwjgl-nanovg&lt;/artifactId&gt;
&lt;version&gt;${lwjgl.version}&lt;/version&gt;
&lt;classifier&gt;${native.target}&lt;/classifier&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
</code></pre>
<p>在开始使用<a href="https://github.com/memononen/nanovg">NanoVG</a>之前我们必须在OpenGL设置一些东西以便示例能够正常工作。我们需要启用对模板测试Stencil Test的支持。到目前为止我们已经讲解了颜色和深度缓冲区但我们没有提到模板缓冲区。该缓冲区为用于控制应绘制哪些像素的每个像素储存一个值整数用于根据储存的值以屏蔽或放弃绘图区域。例如它可以用来以一种简单的方式切割场景的某些部分。我们通过将此行添加到<code>Window</code>类中来启用模板测试(在启用深度测试之后):</p>
<pre><code class="language-java">glEnable(GL_STENCIL_TEST);
</code></pre>
<p>因为我们使用的是另一个缓冲区,所以在每次渲染调用之前,我们还必须注意删除它的值。因此,我们需要修改<code>Renderer</code>类的<code>clear</code>方法:</p>
<pre><code class="language-java">public void clear() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
</code></pre>
<p>我们还将添加一个新的窗口选项来激活抗锯齿Anti-aliasing。因此<code>Window</code>类中,我们将通过如下方式启用它:</p>
<pre><code class="language-java">if (opts.antialiasing) {
glfwWindowHint(GLFW_SAMPLES, 4);
}
</code></pre>
<p>现在我们可以使用<a href="https://github.com/memononen/nanovg">NanoVG</a>库了。我们要做的第一件事就是删掉我们创建的HUD代码即着色器<code>IHud</code>接口,<code>Renderer</code>类中的HUD渲染方法等。你可以在源代码中查看。</p>
<p>在此情况下,新的<code>Hud</code>类将负责其渲染,因此我们不需要将其委托给<code>Renderer</code>类。让我们先定义这个类,它将有一个<code>init</code>方法来设置库和构建HUD所需要的资源。方法定义如下</p>
<pre><code class="language-java">public void init(Window window) throws Exception {
this.vg = window.getOptions().antialiasing ? nvgCreate(NVG_ANTIALIAS | NVG_STENCIL_STROKES) : nvgCreate(NVG_STENCIL_STROKES);
if (this.vg == NULL) {
throw new Exception(&quot;Could not init nanovg&quot;);
}
fontBuffer = Utils.ioResourceToByteBuffer(&quot;/fonts/OpenSans-Bold.ttf&quot;, 150 * 1024);
int font = nvgCreateFontMem(vg, FONT_NAME, fontBuffer, 0);
if (font == -1) {
throw new Exception(&quot;Could not add font&quot;);
}
colour = NVGColor.create();
posx = MemoryUtil.memAllocDouble(1);
posy = MemoryUtil.memAllocDouble(1);
counter = 0;
}
</code></pre>
<p>我们首先要做的是创建一个NanoVG上下文。在本例中我们使用的是OpenGL3.0后端,因此我们引用的是<code>org.lwjgl.nanovg.NanoVGGL3</code>命名空间。如果抗锯齿被启用,我们将设置<code>NVG_ANTIALIAS</code>标志。</p>
<p>接下来,我们使用此前加载到<code>ByteBuffer</code>中的TrueType字体来创建字体。我们为它指定一个名词以便稍后在渲染文本时使用它。关于这点一件很重要的事情是用于加载字体的<code>ByteBuffer</code>必须在使用字体时储存在内存中。也就是说,它不能被回收,否则你将得到一个不错的核心崩溃。这就是将它储存为类属性的原因。</p>
<p>然后,我们创建一个颜色实例和一些有用的变量,这些变量将在渲染时使用。在初始化渲染之前,在游戏初始化方法中调用该方法:</p>
<pre><code class="language-java">@Override
public void init(Window window) throws Exception {
hud.init(window);
renderer.init(window);
...
</code></pre>
<p><code>Hud</code>类还定义了一个渲染方法该方法应在渲染场景后调用以便在其上绘制Hud。</p>
<pre><code class="language-java">@Override
public void render(Window window) {
renderer.render(window, camera, scene);
hud.render(window);
}
</code></pre>
<p>Hud类的<code>render</code>方法的开头如下所示:</p>
<pre><code class="language-java">public void render(Window window) {
nvgBeginFrame(vg, window.getWidth(), window.getHeight(), 1);
</code></pre>
<p>首先必须要做的第一件事是调用<code>nvgBeginFrame</code>方法。所有NanoVG渲染操作都必须保护在<code>nvgBeginFrame</code><code>nvgEndFrame</code>调用之间。<code>nvgBeginFrame</code>接受以下参数:</p>
<ul>
<li>NanoVG环境</li>
<li>要渲染的窗口的大小(宽度和高度)。</li>
<li>像素比。如果需要支持Hi-DPI可以修改此值。对于本例我们只将其设置为1。</li>
</ul>
<p>然后我们创建了几个占据整个屏幕的色带。第一条是这样绘制的:</p>
<pre><code class="language-java">// 上色带
nvgBeginPath(vg);
nvgRect(vg, 0, window.getHeight() - 100, window.getWidth(), 50);
nvgFillColor(vg, rgba(0x23, 0xa1, 0xf1, 200, colour));
nvgFill(vg);
</code></pre>
<p>渲染图形时,应调用的第一个方法是<code>nvgBeginPath</code>它指示NanoVG开始绘制新图形。然后定义要绘制的内容一个矩形填充颜色并通过调用<code>nvgFill</code>绘制它。</p>
<p>你可以查看源代码的其他部分,以了解其余图形是如何绘制的。当渲染文本是,不需要在渲染前调用<code>nvgBeginPath</code></p>
<p>完成所有图形的绘制后,我们只需要调用<code>nvgEndFrame</code>来结束渲染但在离开方法之前还有一件重要的事情要做。我们必须恢复OpenGL状态NanoVG修改OpenGL以执行其操作如果状态未正确还原你可能会看到场景没有正确渲染甚至被擦除。因此我们需要恢复渲染所需的相关OpenGL状态。这是委派到<code>Window</code>类中的:</p>
<pre><code class="language-java">// 还原状态
window.restoreState();
</code></pre>
<p>方法的定义如下:</p>
<pre><code class="language-java">public void restoreState() {
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (opts.cullFace) {
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
}
}
</code></pre>
<p>这就完事了(除了一些其它的清理方法),代码完成了。当你运行示例时,你将得到如下结果:</p>
<p><img alt="Hud" src="../_static/24/hud.png" /></p>
</div>
</div><footer>
<div class="rst-footer-buttons" role="navigation" aria-label="Footer Navigation">
<a href="../23-3d-object-picking/" class="btn btn-neutral float-left" title="三维物体选取"><span class="icon icon-circle-arrow-left"></span> Previous</a>
<a href="../25-optimizations-frustum-culling/" class="btn btn-neutral float-right" title="优化 - 截锥剔除">Next <span class="icon icon-circle-arrow-right"></span></a>
</div>
<hr/>
<div role="contentinfo">
<!-- Copyright etc -->
<p>2019, Mouse0w0</p>
</div>
Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<div class="rst-versions" role="note" aria-label="Versions">
<span class="rst-current-version" data-toggle="rst-current-version">
<span>
<a href="https://github.com/Mouse0w0/lwjglbook-CN-Translation" class="fa fa-github" style="color: #fcfcfc"> GitHub</a>
</span>
<span><a href="../23-3d-object-picking/" style="color: #fcfcfc">&laquo; Previous</a></span>
<span><a href="../25-optimizations-frustum-culling/" style="color: #fcfcfc">Next &raquo;</a></span>
</span>
</div>
<script src="../js/jquery-3.6.0.min.js"></script>
<script>var base_url = "..";</script>
<script src="../js/theme_extra.js"></script>
<script src="../js/theme.js"></script>
<script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>
<script src="../search/main.js"></script>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>