mirror of
https://github.com/mouse0w0/lwjglbook-CN-Translation.git
synced 2025-08-22 20:25:29 +08:00
347 lines
18 KiB
HTML
Executable File
347 lines
18 KiB
HTML
Executable File
<!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 - NanoVG(HUD 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">...
|
||
<dependency>
|
||
<groupId>org.lwjgl</groupId>
|
||
<artifactId>lwjgl-nanovg</artifactId>
|
||
<version>${lwjgl.version}</version>
|
||
</dependency>
|
||
...
|
||
<dependency>
|
||
<groupId>org.lwjgl</groupId>
|
||
<artifactId>lwjgl-nanovg</artifactId>
|
||
<version>${lwjgl.version}</version>
|
||
<classifier>${native.target}</classifier>
|
||
<scope>runtime</scope>
|
||
</dependency>
|
||
</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("Could not init nanovg");
|
||
}
|
||
|
||
fontBuffer = Utils.ioResourceToByteBuffer("/fonts/OpenSans-Bold.ttf", 150 * 1024);
|
||
int font = nvgCreateFontMem(vg, FONT_NAME, fontBuffer, 0);
|
||
if (font == -1) {
|
||
throw new Exception("Could not add font");
|
||
}
|
||
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">« Previous</a></span>
|
||
|
||
|
||
<span><a href="../25-optimizations-frustum-culling/" style="color: #fcfcfc">Next »</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>
|