<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://www.ferdinandlist.de/blog">
  <title>Ferdinand List - Blog</title>
  <subtitle>Just an archive of things and thoughts.</subtitle>
  <link href="https://www.ferdinandlist.de/feed.xml" rel="self"/>
  <link href="https://www.ferdinandlist.de/blog"/>
  <updated>2022-08-04T00:00:00Z</updated>
  <id>https://www.ferdinandlist.de/blog</id>
  <author>
    <name>Ferdinand List</name>
    <email>f.list@posteo.de</email>
  </author>
  <entry>
    <title>[id tech 3] Dynamic shadows</title>
    <link href="https://www.ferdinandlist.de/blog/idtech3_dynamic_shadows/"/>
    <updated>2022-08-04T00:00:00Z</updated>
    <id>https://www.ferdinandlist.de/blog/idtech3_dynamic_shadows/</id>
    <content xml:lang="en" type="html">&lt;p&gt;I stumbled across &lt;a href=&quot;https://www.quake3world.com/forum/viewtopic.php?f=10&amp;amp;t=1146&amp;amp;st=0&amp;amp;sk=t&amp;amp;sd=a&quot;&gt;this old quake3world thread&lt;/a&gt; by user $NulL claiming to have achieved an implementation of dynamic shadows in q3. Since the post is from 2005 and links are of course dead, I went on a hunt to see if I could still find it somehow. Thankfully, as it turned out, &lt;a href=&quot;https://sst13.de/&quot;&gt;sst13&lt;/a&gt; happened to have a copy of the file that he could provide!&lt;/p&gt;
&lt;p&gt;I went ahead and made a new video of it.&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://www.ferdinandlist.de/img/quake/dynamic_shadows/idtech3_dynamic_shadows.mp4&quot; type=&quot;video/mp4&quot; loop=&quot;&quot; controls=&quot;&quot;&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h4 id=&quot;how-it-works&quot; tabindex=&quot;-1&quot;&gt;How it works &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/idtech3_dynamic_shadows/#how-it-works&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The movement of the shadow volume is produced by having it in the same transitioned func_ as the geometry itself.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.ferdinandlist.de/img/quake/dynamic_shadows/editor_shot.jpg&quot; alt=&quot;Editor shot&quot;&gt;&lt;/p&gt;
&lt;p&gt;A shader is used to darken the geomtry hit by the shadow volume. A high &lt;a href=&quot;http://q3map2.robotrenegade.com/docs/shader_manual/general-directives.html#sort&quot;&gt;sort value&lt;/a&gt; of 12 is used to make sure the shadow draws in the correct order on all kinds of shaders.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;textures/null_test/a_shadow_dark&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;	qer_editorimage textures/null_test/shadow.tga&lt;br&gt;	surfaceparm nonsolid&lt;br&gt;	surfaceparm nolightmap&lt;br&gt;	surfaceparm trans&lt;br&gt;	surfaceparm nomarks&lt;br&gt;	surfaceparm nodlight&lt;br&gt;	sort &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;br&gt;	q3map_cloneshader textures/null_test/a_shadow_light&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;		map textures/null_test/shadow_d.tga&lt;br&gt;		blendfunc gl_dst_color gl_src_color&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From the original post, as stated by $NulL:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The outward facing polygons of the shadow volume darken whats already in the framebuffer.&lt;br&gt;
The inward facing ones brighten it up again.&lt;br&gt;
So when you can see both inward and outward facing polys they cancel each other out, but when only the outward facing poly is visiable the area is shadowed.&lt;br&gt;
(You should never directly see an inward facing polygon)&lt;br&gt;
There are some major limitations though. Being depth pass shadows you dont ever want a player&#39;s view to pass into a shadow volume.&lt;br&gt;
There will be a maximum number of shadow polys rendered on top of each other before it fails and the shadow volumes become visable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Apparently there has been an attempt at creating a smooth shadow version as well that got lost in time:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Right, I got a fading one kinda working. I used a gradiant texture instead of alpha blending it. But I carnt get around the values not being able to cancel each other out, so it looks ok from the side or top but from anywhere else the volumes become too visible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;download&quot; tabindex=&quot;-1&quot;&gt;Download &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/idtech3_dynamic_shadows/#download&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/files/leveldesign/test_shadow.zip&quot;&gt;test_shadow.zip [Q3, 240KB]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>[id tech 3] deformVertexes normal</title>
    <link href="https://www.ferdinandlist.de/blog/idtech3_deformVertexes_normal/"/>
    <updated>2022-08-01T00:00:00Z</updated>
    <id>https://www.ferdinandlist.de/blog/idtech3_deformVertexes_normal/</id>
    <content xml:lang="en" type="html">&lt;p&gt;While working on the &lt;a href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/&quot;&gt;water shading sample map&lt;/a&gt; I had an issue with the shader declaration &lt;code&gt;deformVertexes normal&lt;/code&gt; causing the engine to complain about unkown numeric shader parameters.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.ferdinandlist.de/img/quake/deformVertexes_normal/warning_deformvertexes_normal.jpg&quot; alt=&quot;deformVertexes normal console warning&quot;&gt;&lt;/p&gt;
&lt;p&gt;I double checked with the &lt;a href=&quot;http://q3map2.robotrenegade.com/docs/shader_manual/general-directives.html#deformVertexes&quot;&gt;shader manual&lt;/a&gt; which notes the following params for &lt;code&gt;deformVertexes normal&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;deformVertexes normal &amp;lt;div&gt; &amp;lt;func&gt; &amp;lt;base&gt; &amp;lt;amplitude&gt; &amp;lt;freq&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not being able to resolve the issue I went on a hunt online to see if I could find any additional info on the matter. I ended up in the &lt;a href=&quot;https://github.com/raspberrypi/quake3/blob/master/code/renderer/tr_shader.c#L1060&quot;&gt;quake 3 source on github&lt;/a&gt;, surprised to see different params listed for the usage of &lt;code&gt;deformVertex normal&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;deformVertexes normal &amp;lt;frequency&gt; &amp;lt;amplitude&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I adjusted the params in my shader and the warning was gone. However, it was still not quite behaving the way the params suggest. I went ahead and asked nigrum/garux, the project founder of &lt;a href=&quot;https://github.com/Garux/netradiant-custom&quot;&gt;netradiant-custom&lt;/a&gt;, if he had any idea about it and he pointed out to me that he had made fixes to q3map2 as well as corrections to the shader manual resolving the problem. The up to date params are in the shader manual that ships with netradiant-custom and will apparently only apply to the version of q3map2 that is included with it.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;deformVertexes normal &amp;lt;amplitude&gt; &amp;lt;frequency&gt;&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <title>[id tech 3] Water shading</title>
    <link href="https://www.ferdinandlist.de/blog/idtech3_water_shading/"/>
    <updated>2022-07-24T00:00:00Z</updated>
    <id>https://www.ferdinandlist.de/blog/idtech3_water_shading/</id>
    <content xml:lang="en" type="html">&lt;p&gt;I&#39;ve known for a while that Hipshot has used q3map2&#39;s alpha blending features in order to fade out the edges of water volume in order to make the transition to lit surfaces more subtle and less contrasty (for instance on &lt;a href=&quot;https://lvlworld.com/review/id:2126&quot;&gt;solitude&lt;/a&gt;). However, I never actually got to try it myself so I made this little sample map to get an overview of some water shading methods in id tech 3.&lt;/p&gt;
&lt;h3&gt;Post contents&lt;/h3&gt;
&lt;nav class=&quot;table-of-contents&quot;&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/#preface&quot;&gt;Preface &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/#alpha-blending-the-edges-of-water-volumes&quot;&gt;Alpha blending the edges of water volumes &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/#additional-tests&quot;&gt;Additional tests &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/#combining-level-wide-fog-and-water-fog&quot;&gt;Combining level wide fog and water fog &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/#working-with-envmaps-(update-2022-07-29)&quot;&gt;Working with envmaps (update 2022-07-29) &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/#download&quot;&gt;Download &lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/nav&gt;&lt;h4 id=&quot;preface&quot; tabindex=&quot;-1&quot;&gt;Preface &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/#preface&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Origin of the investigation was Hipshot&#39;s water shader that consists of two grainy alpha channel textures blended on top of each other with a slight turb effect. Key here is the &lt;code&gt;alphaGen vertex&lt;/code&gt; directive that makes the shader&#39;s alpha channel depend on q3map2 alpha mod shaders placed on the water volume&#39;s vertices.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// hipshot&#39;s water shader for alpha blending to zero&lt;/span&gt;&lt;br&gt;&lt;br&gt;textures/ct_testWaterBlend/water_01&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;	qer_editorimage textures/ct_testWaterBlend/hipshot_water.tga&lt;br&gt;	q3map_globaltexture&lt;br&gt;	surfaceparm trans&lt;br&gt;	surfaceparm nonsolid&lt;br&gt;	surfaceparm nomarks&lt;br&gt;	surfaceparm nolightmap&lt;br&gt;	nopicmip&lt;br&gt;	noMipMaps&lt;br&gt;	cull none&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;		map textures/ct_testWaterBlend/hipshot_water.tga&lt;br&gt;		blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA&lt;br&gt;		rgbGen identity&lt;br&gt;		alphaGen vertex	&lt;br&gt;		tcmod scale &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;			&lt;br&gt;		tcMod turb &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; .&lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; .&lt;span class=&quot;token number&quot;&gt;015&lt;/span&gt;	&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;	&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;		map textures/ct_testWaterBlend/hipshot_water2.tga&lt;br&gt;		blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA&lt;br&gt;		rgbGen identity&lt;br&gt;		alphaGen vertex	&lt;br&gt;		tcmod scale &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;			&lt;br&gt;		tcMod turb &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; -.&lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; -.&lt;span class=&quot;token number&quot;&gt;015&lt;/span&gt;				&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;	&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Read more about alphaMod shaders &lt;a href=&quot;http://q3map2.robotrenegade.com/docs/shader_manual/q3map-global-directives.html#q3map_alphaMod&quot;&gt;here&lt;/a&gt;.&lt;br&gt;
In case you are missing the alphaMod shaders, you can download them &lt;a href=&quot;http://www.icculus.org/gtkradiant/downloads.html#quake3extras&quot;&gt;here&lt;/a&gt;. For reference, I included a sample shader below.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// alpha fade shader&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;// (c) 2004 randy reddig&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;// http://www.shaderlab.com&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;// distribution, in part or in whole, in any medium, permitted&lt;/span&gt;&lt;br&gt;&lt;br&gt;textures/common/alpha_100&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;	qer_trans &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt;&lt;br&gt;	q3map_alphaMod volume&lt;br&gt;	q3map_alphaMod scale &lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;br&gt;	surfaceparm nodraw&lt;br&gt;	surfaceparm nonsolid&lt;br&gt;	surfaceparm trans&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The alphaMod shaders are placed on small brush poles that get aligned with the vertices of the water volume to be alpha blended. Gathering the water volume brushes as well as the alphaMod shader brushes in a &lt;code&gt;func_group&lt;/code&gt; will limit the blending effect to that particular group. See the sample map at the bottom of the page as an example.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/blending_editor.jpg&quot; alt=&quot;Editor view&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4 id=&quot;alpha-blending-the-edges-of-water-volumes&quot; tabindex=&quot;-1&quot;&gt;Alpha blending the edges of water volumes &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/#alpha-blending-the-edges-of-water-volumes&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;As a result of alpha blending the water volume edges, you receive a smooth transition to the neighboring materials. In this example, the water shader fades to zero. However any alpha channel intensity is possible to use.&lt;/p&gt;
&lt;div class=&quot;gallery twoCol&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/blending_none.jpg&quot; alt=&quot;Default: No blending&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/blending_zero.jpg&quot; alt=&quot;Blending the edges of the water volume to zero&quot;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4 id=&quot;additional-tests&quot; tabindex=&quot;-1&quot;&gt;Additional tests &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/#additional-tests&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Below you can see additional tests that I executed.&lt;/p&gt;
&lt;p&gt;Tests include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;using fog inside water volumes&lt;/li&gt;
&lt;li&gt;using faint level wide fog along with water fog&lt;/li&gt;
&lt;li&gt;using alpha blending to fade water volumes to zero at the edges&lt;/li&gt;
&lt;li&gt;using solid color alpha blended layers on top of water volumes&lt;/li&gt;
&lt;li&gt;using envmaps on water volumes&lt;/li&gt;
&lt;li&gt;various combinations of the above&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The shader including a solid color stage can be an option for cases where you are already using a thicker level wide fog and want to have your water a little more diffuse without producing fog conflicts.&lt;/p&gt;
&lt;div class=&quot;gallery twoCol&quot;&gt;
&lt;img loading=&quot;lazy&quot; src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/01.jpg&quot; alt=&quot;Alpha Blending without fog, without solid color, without envmap&quot; title=&quot;Alpha Blending without fog, without solid color, without envmap&quot;&gt;
&lt;img loading=&quot;lazy&quot; src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/02.jpg&quot; alt=&quot;Alpha Blending and fog, without solid color, without envmap&quot; title=&quot;Alpha Blending and fog, without solid color, without envmap&quot;&gt;
&lt;img loading=&quot;lazy&quot; src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/03.jpg&quot; alt=&quot;Alpha Blending, fog and solid color, without envmap&quot; title=&quot;Alpha Blending, fog and solid color, without envmap&quot;&gt;
&lt;img loading=&quot;lazy&quot; src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/04.jpg&quot; alt=&quot;Alpha Blending, fog, solid color and envmap&quot; title=&quot;Alpha Blending, fog, solid color and envmap&quot;&gt;
&lt;img loading=&quot;lazy&quot; src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/05.jpg&quot; alt=&quot;Alpha Blending, fog, and envmap, without solid color&quot; title=&quot;Alpha Blending, fog, and envmap, without solid color&quot;&gt;
&lt;img loading=&quot;lazy&quot; src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/06.jpg&quot; alt=&quot;Fog, and envmap, without solid color and alpha blending&quot; title=&quot;Fog, and envmap, without solid color and alpha blending&quot;&gt;
&lt;/div&gt;
&lt;p&gt;Here is the complete modification of hipshot&#39;s water shader including solid color stage and envmap stage.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// hipshot&#39;s water shader for alpha blending to zero&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;// with a solid color layer and an envmap&lt;/span&gt;&lt;br&gt;&lt;br&gt;textures/ct_testWaterBlend/water_03&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;	qer_editorimage textures/ct_testWaterBlend/hipshot_water.tga&lt;br&gt;	q3map_globaltexture&lt;br&gt;	surfaceparm trans&lt;br&gt;	surfaceparm nonsolid&lt;br&gt;	surfaceparm nomarks&lt;br&gt;	surfaceparm nolightmap&lt;br&gt;	nopicmip&lt;br&gt;	noMipMaps&lt;br&gt;	cull none&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;		map textures/ct_testWaterBlend/hipshot_water.tga&lt;br&gt;		blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA&lt;br&gt;		rgbGen identity&lt;br&gt;		alphaGen vertex	&lt;br&gt;		tcmod scale &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;			&lt;br&gt;		tcMod turb &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; .&lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; .&lt;span class=&quot;token number&quot;&gt;015&lt;/span&gt;	&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;	&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;		map textures/ct_testWaterBlend/hipshot_water2.tga&lt;br&gt;		blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA&lt;br&gt;		rgbGen identity&lt;br&gt;		alphaGen vertex	&lt;br&gt;		tcmod scale &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;			&lt;br&gt;		tcMod turb &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; -.&lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; -.&lt;span class=&quot;token number&quot;&gt;015&lt;/span&gt;				&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;	&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;		map textures/ct_testWaterBlend/waterColor_02_50.tga&lt;br&gt;		blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA&lt;br&gt;		rgbGen identity&lt;br&gt;		alphaGen vertex&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;		&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;		map textures/ct_testWaterBlend/waterFX_01.tga&lt;br&gt;		rgbGen identity&lt;br&gt;		tcGen environment &lt;br&gt;		blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA&lt;br&gt;		alphaGen vertex	&lt;br&gt;		tcmod scale &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt;&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;	&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A notable experiment to me is using an alpha channel controled solid color envmap. While the envmap image itself is just a solid light grey, the alpha channel is a ripple kind b/w texture as seen below. This method allows for controling the envmap color separately from the opacity.&lt;/p&gt;
&lt;div class=&quot;gallery&quot;&gt;
&lt;img loading=&quot;lazy&quot; src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/waterFX_alphaChannel.jpg&quot; alt=&quot;The envmap alpha Chanel&quot; title=&quot;The envmap alpha Chanel&quot; class=&quot;small&quot;&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4 id=&quot;combining-level-wide-fog-and-water-fog&quot; tabindex=&quot;-1&quot;&gt;Combining level wide fog and water fog &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/#combining-level-wide-fog-and-water-fog&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;As a part of this sample map I wanted to reinvestigate on the issue of using multiple fog volumes in a map. While combining two thick fog volumes produces rendering errors as seen in image 1, using a faint level wide fog along with a thick water fog is not actually problematic as seen in image 3. I am a fan of using thin level wide fog as it eases the contrast of the lightmap just a little and can be used to give the overall lighting a subtle tint. Comparing images 2 and 3 you can see that while in image 2 there are pitch black areas with actual information loss, in image 3 these areas get pulled up just a tiny bit revealing the underlaying geometry. Additionally, shadows in image 3 appear with a slight blue tint instead of just greyscale.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/fog_error.jpg&quot; alt=&quot;Conflicting fog volumes&quot;&gt;&lt;/p&gt;
&lt;div class=&quot;gallery twoCol&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/fog_none.jpg&quot; alt=&quot;Without level wide fog&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/fog_faint.jpg&quot; alt=&quot;With faint level wide fog&quot;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4 id=&quot;working-with-envmaps-(update-2022-07-29)&quot; tabindex=&quot;-1&quot;&gt;Working with envmaps (update 2022-07-29) &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/#working-with-envmaps-(update-2022-07-29)&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;On a real water surface you would normally be able to observe a reflection of the environment, continuously distorted by the water&#39;s movement. The tool we have in id tech 3 to simulate this effect is using an &lt;code&gt;tcgen environment&lt;/code&gt; shader stage, commonly referred to as envmap. The challenge here however is to bring in the element of distortion and not make the water surface look like a mirror.&lt;br&gt;
I have extended the sample .map with a row of examples on how envmaps could be used, ranging from tesselation of flat surfaces with q3map2&#39;s &lt;code&gt;tessSize&lt;/code&gt; over different &lt;code&gt;deformVertex&lt;/code&gt; approaches and using actual tesselated deformed meshes created in blender in combination with &lt;code&gt;deformVertex move&lt;/code&gt; and &lt;code&gt;tcmod&lt;/code&gt; modifications of the envmap.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/result_mesh_turb.jpg&quot; alt=&quot;Envmap on mesh with tcmod turb&quot;&gt;&lt;/p&gt;
&lt;p&gt;As a conclusion I would say that the most satisfying results are definitely produced by applying your water shader to a tesselated deformed mesh in combination with &lt;code&gt;deformVertex move&lt;/code&gt; or &lt;code&gt;tcmod turb&lt;/code&gt; on the envmap stage. While both approaches work, &lt;code&gt;deformVertex&lt;/code&gt; move may actually not be feasible geometrically in some scenarios as the entire mesh will actually appear moving. In these cases using a turb, maybe in combination with a slight scroll or stretch, on the envmap is a fine compromise.&lt;/p&gt;
&lt;p&gt;Worth mentioning as well is the approach of using &lt;code&gt;deformVertex normal&lt;/code&gt; in order to produce an interesting simulated reflection. While the examples included in the sample map use a low &lt;code&gt;tessSize&lt;/code&gt; of 16, good compromise in terms of performance may be found with a little higher tessSize. Overall these methods of shading water will take a hit on your tris count if used extensively. While I do not have any extensive details on the matter, using the mesh without the forceMeta flag, should keep it cheap in terms of performance.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/tesselation.jpg&quot; alt=&quot;Tesselated deformed mesh&quot;&gt;&lt;br&gt;
The tesselated and deformed mesh with &lt;code&gt;r_showtris 1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/result_mesh_deform_move.mp4&quot; type=&quot;video/mp4&quot; loop=&quot;&quot; controls=&quot;&quot;&gt;&lt;/video&gt;&lt;br&gt;
Water shader with &lt;code&gt;deformVertex move&lt;/code&gt; used on mesh&lt;/p&gt;
&lt;p&gt;&lt;video src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/result_mesh_turb.mp4&quot; type=&quot;video/mp4&quot; loop=&quot;&quot; controls=&quot;&quot;&gt;&lt;/video&gt;&lt;br&gt;
Water shader with &lt;code&gt;tcmod turb&lt;/code&gt; on the envmap used on mesh&lt;/p&gt;
&lt;p&gt;Here is the complete turb shader used on the mesh, inclding alpha blended dirt stages.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;// hipshot&#39;s water shader for alpha blending to zero&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;// with an envmap with tcmod turb&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;token comment&quot;&gt;// for use on a tesselated mesh&lt;/span&gt;&lt;br&gt;textures/ct_testWaterBlend/water_tess_01-turb&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;	qer_editorimage textures/ct_testWaterBlend/hipshot_water.tga&lt;br&gt;	q3map_globaltexture&lt;br&gt;	surfaceparm trans&lt;br&gt;	surfaceparm nonsolid&lt;br&gt;	surfaceparm nomarks&lt;br&gt;	surfaceparm nolightmap&lt;br&gt;	nopicmip&lt;br&gt;	noMipMaps&lt;br&gt;	cull none&lt;br&gt;	deformVertexes wave &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt; sin &lt;span class=&quot;token number&quot;&gt;-2&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.2&lt;/span&gt; &lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;		map textures/ct_testWaterBlend/hipshot_water.tga&lt;br&gt;		blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA&lt;br&gt;		rgbGen identity&lt;br&gt;		alphaGen vertex	&lt;br&gt;		tcmod scale &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;			&lt;br&gt;		tcMod turb &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; .&lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; .&lt;span class=&quot;token number&quot;&gt;015&lt;/span&gt;	&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;	&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;		map textures/ct_testWaterBlend/hipshot_water2.tga&lt;br&gt;		blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA&lt;br&gt;		rgbGen identity&lt;br&gt;		alphaGen vertex	&lt;br&gt;		tcmod scale &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;			&lt;br&gt;		tcMod turb &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; -.&lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; -.&lt;span class=&quot;token number&quot;&gt;015&lt;/span&gt;				&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;	&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br&gt;		map textures/ct_testWaterBlend/waterFX_02-green.tga&lt;br&gt;		rgbGen identity&lt;br&gt;		tcGen environment &lt;br&gt;		blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA&lt;br&gt;		alphaGen vertex	&lt;br&gt;		tcmod scale &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;br&gt;		tcMod turb &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; .&lt;span class=&quot;token number&quot;&gt;025&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; .&lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;	&lt;br&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;	&lt;br&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to reside to a conventional envmap on brushes, you might want to check out tessSize whatsoever as the way q3map2 triangulates the geometry may affect the appearance of the envmap.&lt;/p&gt;
&lt;p&gt;Lastly, one thing I did in fact not know was that alphaMod brushes can be used in a linear way instead of just placing them on single vertices. Additionally, if you want to alpha blend an imported mesh, you cannot have your alphaMod brushes in a &lt;code&gt;func_group&lt;/code&gt; as models cannot be part of that group and thus the blending declarative will have no effect on any geometry. Leave everything as part of the worldspawn entity.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://www.ferdinandlist.de/img/quake/testWaterBlend/editor_alphaMod_brushes_long.jpg&quot; alt=&quot;alphaMod brushes on mesh&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;download&quot; tabindex=&quot;-1&quot;&gt;Download &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/idtech3_water_shading/#download&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This map&#39;s water shader and sky shader, as well as the corresponding materials were originally created by Hipshot. The .map source file is included with the pk3.&lt;br&gt;
I included the mesh .obj used for the envmap tests with the pk3. Also included is the psd file for the envmap. Special thanks to quBit for giving me a lot of input on shading possiblities. Thanks to nigrum/garux for netradiant custom and answering a lot of my questions.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/files/leveldesign/testWaterBlend_QL.zip&quot;&gt;Download sample map [Quake Live, 5mb]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/files/leveldesign/testWaterBlend_Q3.zip&quot;&gt;Download sample map [Quake III Arena, 5mb]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>New portfolio site launched</title>
    <link href="https://www.ferdinandlist.de/blog/new-portfolio-site/"/>
    <updated>2022-07-22T00:00:00Z</updated>
    <id>https://www.ferdinandlist.de/blog/new-portfolio-site/</id>
    <content xml:lang="en" type="html">&lt;p&gt;For a a fear years now I have been trying different approaches to operating a low maintenance effort portfolio site in a sustainable and archivable way.&lt;/p&gt;
&lt;p&gt;This is my latest approach relying on the static site generator &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;11ty&lt;/a&gt; and gitlab ci/cd for deployment. 11ty allows for easy content management with re-usable templates relying on templating languages like &lt;a href=&quot;https://de.wikipedia.org/wiki/Markdown&quot;&gt;Markdown&lt;/a&gt; or &lt;a href=&quot;https://mozilla.github.io/nunjucks/&quot;&gt;Nunjucks&lt;/a&gt; while incorporating the powers of CSS and Javascript. Site and content are managed in a git repository on gitlab and re-deploy automatically to my webserver when a commit is pushed to the main branch.&lt;br&gt;
Since the output of 11ty is just plain static html and css, the site can be easily archived while still offering me a reasonably dynamic interface for content management.&lt;/p&gt;
&lt;p&gt;The main purpose of this project is documenting my &lt;a href=&quot;https://www.ferdinandlist.de/&quot;&gt;architecture projects&lt;/a&gt;. However, since I get asked about my &lt;a href=&quot;https://www.ferdinandlist.de/leveldesign&quot;&gt;level design projects&lt;/a&gt; every once in a while, I decided to give them an own subsite. Then there is the blog you are reading which shall function more as a personal archive rather than something people may actively follow.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Masking gitlab ci/cd env variables using base64</title>
    <link href="https://www.ferdinandlist.de/blog/gitlab_cicd_env_var_masking_base64/"/>
    <updated>2022-07-22T00:00:00Z</updated>
    <id>https://www.ferdinandlist.de/blog/gitlab_cicd_env_var_masking_base64/</id>
    <content xml:lang="en" type="html">&lt;p&gt;Gitlab has requirements with regards to special chars and length for environment variables to be maskable. These can be circumvented using base64 encoding which containss no special chars. Store the env variable encoded and masked and decode it during the execution of your gitlab pipeline.&lt;/p&gt;
&lt;h4 id=&quot;example%3A-private-ssh-key&quot; tabindex=&quot;-1&quot;&gt;Example: private ssh key &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/gitlab_cicd_env_var_masking_base64/#example%3A-private-ssh-key&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Converting to base64:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; id_rsa_gitlab_cicd &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; base64 &lt;span class=&quot;token parameter variable&quot;&gt;-w0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; id_rsa_gitlab_cicd_base64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Converting back to clear text inside your gitlab pipeline:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;  script:&lt;br&gt;  - &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Deploying!&quot;&lt;/span&gt;&lt;br&gt;  - &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${SSH_PRIVATE_KEY}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; base64 &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; id_rsa_gitlab_cicd_decoded&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;links&quot; tabindex=&quot;-1&quot;&gt;Links &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/gitlab_cicd_env_var_masking_base64/#links&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://gitlab.com/gitlab-org/gitlab/-/issues/196871&quot;&gt;https://gitlab.com/gitlab-org/gitlab/-/issues/196871&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/60247900/gitlab-masking-variables&quot;&gt;https://stackoverflow.com/questions/60247900/gitlab-masking-variables&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Deploy an 11ty site using gitlab ci/cd pipelines</title>
    <link href="https://www.ferdinandlist.de/blog/gitlab_cicd_deploy_11ty_site/"/>
    <updated>2022-07-22T00:00:00Z</updated>
    <id>https://www.ferdinandlist.de/blog/gitlab_cicd_deploy_11ty_site/</id>
    <content xml:lang="en" type="html">&lt;p&gt;Just a link drop about deploying a site built with 11ty using gitlab CI/CD pipelines&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://quentin.delcourt.be/blog/2020-02-10_eleventy-gitlab-ci-pipeline/index.html&quot;&gt;https://quentin.delcourt.be/blog/2020-02-10_eleventy-gitlab-ci-pipeline/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gitlab.com/gitlab-examples/ssh-private-key/-/blob/master/.gitlab-ci.yml&quot;&gt;https://gitlab.com/gitlab-examples/ssh-private-key/-/blob/master/.gitlab-ci.yml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>The language of arena FPS level design</title>
    <link href="https://www.ferdinandlist.de/blog/language_of_afps_leveldesign/"/>
    <updated>2017-03-05T00:00:00Z</updated>
    <id>https://www.ferdinandlist.de/blog/language_of_afps_leveldesign/</id>
    <content xml:lang="en" type="html">&lt;p&gt;This is an archived post &lt;a href=&quot;https://www.plusforward.net/post/21433/The-Language-of-Arena-FPS-Level-Design/&quot;&gt;originally published on plusforward&lt;/a&gt; in 2017.&lt;/p&gt;
&lt;h3&gt;Post contents&lt;/h3&gt;
&lt;nav class=&quot;table-of-contents&quot;&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/blog/language_of_afps_leveldesign/#what-is-the-problem%3F&quot;&gt;What Is The Problem? &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/blog/language_of_afps_leveldesign/#approaching-the-problem&quot;&gt;Approaching The Problem &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/blog/language_of_afps_leveldesign/#my-proposal&quot;&gt;My Proposal &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.ferdinandlist.de/blog/language_of_afps_leveldesign/#current-pool-of-patterns-(to-be-updated)&quot;&gt;Current pool of patterns (to be updated) &lt;/a&gt;&lt;ol&gt;&lt;/ol&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/nav&gt;&lt;h4 id=&quot;what-is-the-problem%3F&quot; tabindex=&quot;-1&quot;&gt;What Is The Problem? &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/language_of_afps_leveldesign/#what-is-the-problem%3F&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Studying architecture, I&#39;ve spent a great portion of the recent years thinking about what makes environments sufficient to their requirements or what makes them whole. At the same time, arena fps mapping is something that has always been in the back of my mind. The conditions are kind of similar for creating real spaces and virtual levels. There is a context for these environments, and certain geometries create forces that influence &amp;quot;users&amp;quot; in their actions. Sometimes the designers introduce forces they could not predict. Just like architecture, arena fps map making has never been fully figured out and certainly never will as long as we rely on individual intellects for telling us how maps should be made. Part of that is surely because of the fact that the Quake games which kicked off competitive arena fps, are older than the profession of the level designer as we know it today. Quake mapping has never been systematized although there have been attempts (which again nobody had the competencies to verify). I&#39;m not claiming I have these competencies, my judgement is just as limited as anyone eles&#39;.&lt;/p&gt;
&lt;h4 id=&quot;approaching-the-problem&quot; tabindex=&quot;-1&quot;&gt;Approaching The Problem &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/language_of_afps_leveldesign/#approaching-the-problem&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Now where am I going with this? Obviously, map design in arena fps is governed by the respective game&#39;s mechanics, and apart from that by the player skill. If we consider the case of a professional gamer who can perfectly use all of the game&#39;s mechanics, map design just is a direct response to the game&#39;s mechanics. A game&#39;s mechanics however, aren&#39;t only developer made. Developers suffer the same problem as other designers: They sometimes fail to comprehend the consequences of their actions (which I guess is human). By making a game accessible to a playerbase, it is going to be tested and exploited. New dependencies arise by how the players interact with the framework that the game is and also by how they interact with each other. This effect is not immediate, it&#39;s a process driven by the contribution(s) of many. To get back to the core, map design, depends on a game&#39;s mechanics, which are not only driven by the developers but also by the players and the interaction between them. It is a node in the network of dependencies that make a good arena fps. I think it is pretty safe to say that in order to make a good level, one is obligated to understand the game&#39;s mechanics as described above.&lt;/p&gt;
&lt;h4 id=&quot;my-proposal&quot; tabindex=&quot;-1&quot;&gt;My Proposal &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/language_of_afps_leveldesign/#my-proposal&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;How to go about that though!? In our competetive map pools, we usually have five to seven maps, all of which are essentially unique. However, all of them seem to work which shows that the issue I&#39;m discussing here is a complex one. My research in the context of architecture has made me stumble across Christopher Alexander&#39;s concept of pattern languages. To not get too theoretical here, let&#39;s call this a language or network in which the words or nodes are essentially descriptions of situations and actions present in living environments. All of the nodes are linked to each other in a specific way so that each node needs certain sub nodes to be complemented but at the same time complements other nodes &amp;quot;above it&amp;quot;.&lt;/p&gt;
&lt;p&gt;The very idea is to help people understand problem structures and to give them an instruction on how to resolve them. This is all rooted in the idea of solving a problem by understanding a problem; which in my eyes is exactly what has to happen in respect to level design in arena fps.&lt;/p&gt;
&lt;p&gt;How many more decent duel maps could we get if every designer knew about the design relevant nodes, &amp;quot;initial spawns&amp;quot;, &amp;quot;inital control distribution&amp;quot;, &amp;quot;playing out of control&amp;quot;, &amp;quot;control shifts&amp;quot;, &amp;quot;respawns&amp;quot;, &amp;quot;making noise&amp;quot;, &amp;quot;early game&amp;quot;, &amp;quot;late game&amp;quot;, &amp;quot;high ground advantage&amp;quot;, &amp;quot;fake rocket jump&amp;quot;, &amp;quot;armor distribution&amp;quot; to just name a few potential nodes of this virtual network that describes arena fps design. Enabling every map maker to understand the connection between those terms, visually comprehending what connections each one of them has, would be a first step towards creating an objective understanding of making suitable levels for arena fps.&lt;/p&gt;
&lt;p&gt;If a single person however, was able to set up a complete &amp;quot;whole&amp;quot; network like this then surely we&#39;d have it already. Fact is though, that pretty much no one, neither the best designers, nor the best pro players are able to put their thoughts down in a way that gives us a whole perspective like this. In my opinion, this can only be a collaborative community task.&lt;/p&gt;
&lt;p&gt;I&#39;d like to kick off a web interface to establish this and combine it with my architecture research next term. Please feel invited to join the discussion on this topic.&lt;/p&gt;
&lt;h4 id=&quot;current-pool-of-patterns-(to-be-updated)&quot; tabindex=&quot;-1&quot;&gt;Current pool of patterns (to be updated) &lt;a class=&quot;header-anchor&quot; href=&quot;https://www.ferdinandlist.de/blog/language_of_afps_leveldesign/#current-pool-of-patterns-(to-be-updated)&quot;&gt;§&lt;/a&gt;&lt;/h4&gt;
&lt;h5&gt;Unsorted&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;initial spawns&lt;/li&gt;
&lt;li&gt;inital control distribution&lt;/li&gt;
&lt;li&gt;playing out of control&lt;/li&gt;
&lt;li&gt;control shifts&lt;/li&gt;
&lt;li&gt;respawns&lt;/li&gt;
&lt;li&gt;making noise&lt;/li&gt;
&lt;li&gt;early game&lt;/li&gt;
&lt;li&gt;late game&lt;/li&gt;
&lt;li&gt;high ground advantage&lt;/li&gt;
&lt;li&gt;fake rocket jump&lt;/li&gt;
&lt;li&gt;armor distribution&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;On the dependencies of major items&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Shortest Item Connection&lt;/li&gt;
&lt;li&gt;Safest Item Connection&lt;/li&gt;
&lt;li&gt;Narrow Threshold (choke points that don&#39;t give a lot of room to dodge)&lt;/li&gt;
&lt;li&gt;Change in Elevation (including the different forces introduced by jumppads, teles, rocket jumping)&lt;/li&gt;
&lt;li&gt;Control Shifts&lt;/li&gt;
&lt;li&gt;Player Delays&lt;/li&gt;
&lt;li&gt;Item Delays&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;On the geometry around major items&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Defendable Positions&lt;/li&gt;
&lt;li&gt;Vulnerable Positions&lt;/li&gt;
&lt;li&gt;Items on a Platform&lt;/li&gt;
&lt;li&gt;Items on a Pillar&lt;/li&gt;
&lt;li&gt;Items on Even Ground&lt;/li&gt;
&lt;li&gt;Items in Dead Ends&lt;/li&gt;
&lt;li&gt;Items in Alcoves&lt;/li&gt;
&lt;li&gt;Items under Drop Downs&lt;/li&gt;
&lt;li&gt;Items at the top of a staircase&lt;/li&gt;
&lt;li&gt;Floating Items&lt;/li&gt;
&lt;li&gt;Items in Water&lt;/li&gt;
&lt;li&gt;Moving to an Item spawn&lt;/li&gt;
&lt;li&gt;Visibility of the Item Spawn(long range vulnerability e.g. rail)&lt;/li&gt;
&lt;li&gt;Narrowness of an Item Spawn (splash vulnerability e.g. rockets)&lt;/li&gt;
&lt;li&gt;Close Player Respawns&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
</feed>