# Question
Title: How can I draw outlines around 3D models?
How can I draw outlines around 3D models? I'm referring to something like the effects in a recent Pokemon game, which appear to have a single-pixel outline around them:

# Answer
I don't think any of the other answers here will achieve the effect in Pokémon X/Y. I can't know exactly how it's done, but I figured out a way which seems like pretty much what they do in the game.

In Pokémon X/Y, outlines are drawn both around the silhouette edges and on other non-silhouette edges (like where Raichu's ears meet his head in the following screenshot).

Looking at Raichu's mesh in Blender, you can see the ear (highlighted in orange above) is just a separate, disconnected object which intersects the head, creating an abrupt change in the surface normals.

Based on that, I tried generating the outline based on the normals, which requires rendering in two passes:

**First pass**: Render the model (textured and cel-shaded) without the outlines, and render the camera-space normals to a second render target.

**Second pass**: Do a full-screen edge detection filter over the normals from the first pass.

The first two images below show the outputs of the first pass. The third is the outline by itself, and the last is the final combined result.

Here's the OpenGL fragment shader I used for edge detection in the second pass. It's the best I was able to come up with, but there might be a better way. It's probably not very well optimized either.

```
// first render target from the first pass
uniform sampler2D uTexColor;
// second render target from the first pass
uniform sampler2D uTexNormals;

uniform vec2 uResolution;

in vec2 fsInUV;

out vec4 fsOut0;

void main(void)
{
  float dx = 1.0 / uResolution.x;
  float dy = 1.0 / uResolution.y;

  vec3 center = sampleNrm( uTexNormals, vec2(0.0, 0.0) );

  // sampling just these 3 neighboring fragments keeps the outline thin.
  vec3 top = sampleNrm( uTexNormals, vec2(0.0, dy) );
  vec3 topRight = sampleNrm( uTexNormals, vec2(dx, dy) );
  vec3 right = sampleNrm( uTexNormals, vec2(dx, 0.0) );

  // the rest is pretty arbitrary, but seemed to give me the
  // best-looking results for whatever reason.

  vec3 t = center - top;
  vec3 r = center - right;
  vec3 tr = center - topRight;

  t = abs( t );
  r = abs( r );
  tr = abs( tr );

  float n;
  n = max( n, t.x );
  n = max( n, t.y );
  n = max( n, t.z );
  n = max( n, r.x );
  n = max( n, r.y );
  n = max( n, r.z );
  n = max( n, tr.x );
  n = max( n, tr.y );
  n = max( n, tr.z );

  // threshold and scale.
  n = 1.0 - clamp( clamp((n * 2.0) - 0.8, 0.0, 1.0) * 1.5, 0.0, 1.0 );

  fsOut0.rgb = texture(uTexColor, fsInUV).rgb * (0.1 + 0.9*n);
}

```

And before rendering the first pass I clear the normals' render target to a vector facing away from the camera:

```
glDrawBuffer( GL_COLOR_ATTACHMENT1 );
Vec3f clearVec( 0.0, 0.0, -1.0f );
// from normalized vector to rgb color; from [-1,1] to [0,1]
clearVec = (clearVec + Vec3f(1.0f, 1.0f, 1.0f)) * 0.5f;
glClearColor( clearVec.x, clearVec.y, clearVec.z, 0.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

```

I read somewhere (I'll put a link in the comments) that the Nintendo 3DS uses a fixed-function pipeline instead of shaders, so I guess this can't be the way it's done in the game exactly, but for now I'm convinced my method is close enough.
> 37 votes

# Answer
This effect is particularly common in games that make use of cel shading effects, but is actually something that can be applied independently of the cel shading style.

What you are describing is called "feature edge rendering," and is in general process of highlighting the various contours and outlines of a model. There are many techniques available and many papers on the subject.

A simple technique is to render only the silhouette edge, the outmost outline. This can be done as simply as rendering the original model with a stencil write, and then rendering it again in thick wireframe mode, only where there was no stencil value. See here for an example implementation.

That will not highlight the interior contour and crease edges, though (as shown in your pictures). Generally, to do that effectively, you need to extract information about the mesh's edges (based on discontinuities in the face normals on either side of the edge, and build up a data structure representing each edge.

You can then write shaders to extrude or otherwise render those edges as regular geometry overtop your base model (or in conjunction with it). The position of an edge, and normals of the adjacent faces relative to the view vector, are used to determine if a specific edge can be drawn.

You can find further discussion, details and papers with various examples on the internet. For example:
> 18 votes

# Answer
For *smooth* models (very important), this effect is fairly simple. In your fragment/pixel shader you will need the normal of the fragment being shaded. If it is very close to perpendicular (`dot(surface_normal,view_vector) <= .01` \- you might need to play with that threshold) then color the fragment black instead of its usual color.

This approach "consumes" a little bit of the model to do the outline. This may or may not be what you want. It's very difficult to tell from the Pokemon picture if this is what is being done. It depends on if you expect the outline to be included in any silhouette of the character or if you'd rather have the outline enclose the silhouette (which requires a different technique).

The highlight will be on any part of the surface where it transitions from front-facing to back-facing, including "inner edges" (like the legs on the green Pokemon, or its head - some other techniques would not add any outline to those).

Objects that have hard, non-smooth edges (like a cube) will not receive a highlight in the desired locations with this approach. That means this approach is not an option at all in some cases; I have no idea if Pokemon models are all smooth or not.
> 9 votes

# Answer
The simplest way to do this, common on older hardware before pixel/fragment shaders, and still used on mobile, is to duplicate the model, reverse the vertex winding order so that the model displays inside out (or if you want to, you can do this in your 3D asset creation tool, say Blender, by flipping surface normals -- same thing), then expand the entire duplicate slightly around it's centre, and finally colour/texture this duplicate completely black. This results in outlines around your original model, *if* it's a simple model such as a cube. For more complex models with concave forms (such as that in the image below), it is necessary to manually tweak the duplicate model to be somewhat "fatter" than its original counterpart, like a Minkowski Sum in 3D. You could start by pushing each vertex out a bit along its normal to form the outline mesh, as Blender's Shrink/Fatten transform does.

Screen space / pixel shader approaches tend to be slower and harder to implement *well*, but OTOH don't double the number of vertices in your world. So if you're doing high poly work, best opt for that approach. Given modern console and desktop capacity for processing geometry, I'd not worry about a factor of 2 *at all*. Cartoon-style = low poly for sure, thus duplicating geometry is easiest.

You can test the effect for yourself in e.g. Blender without touching any code. Outlines should look like the image below, note how some are internal, e.g. under arm. More detail here.

.
> 8 votes

# Answer
One of the ways to make an outline is to use our models normal vectors. Normal vectors are vectors that are perpendicular to their surface (pointing away from the surface). The trick here is to split your character model into two parts. The vertices that are facing the camera and the vertices that are facing away from the camera. We will call them FRONT and BACK respectively.

For the outline we take our BACK vertices and move them slightly in the direction of their normal vectors. Think about it like making the part of our character that is facing away from the camera a little fatter. After we have that done, we assign them a color of our choice and we have a nice outline.

```
Shader "Custom/OutlineShader" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _Outline("Outline Thickness", Range(0.0, 0.3)) = 0.002
        _OutlineColor("Outline Color", Color) = (0,0,0,1)
    }

    CGINCLUDE
    #include "UnityCG.cginc"

    sampler2D _MainTex;
    half4 _MainTex_ST;

    half _Outline;
    half4 _OutlineColor;

    struct appdata {
        half4 vertex : POSITION;
        half4 uv : TEXCOORD0;
        half3 normal : NORMAL;
        fixed4 color : COLOR;
    };

    struct v2f {
        half4 pos : POSITION;
        half2 uv : TEXCOORD0;
        fixed4 color : COLOR;
    };
    ENDCG

    SubShader
    {
        Tags {
            "RenderType"="Opaque"
            "Queue" = "Transparent"
        }

        Pass{
            Name "OUTLINE"

            Cull Front

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            v2f vert(appdata v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                half3 norm = mul((half3x3)UNITY_MATRIX_IT_MV, v.normal);
                half2 offset = TransformViewToProjection(norm.xy);
                o.pos.xy += offset * o.pos.z * _Outline;
                o.color = _OutlineColor;
                return o;
            }

            fixed4 frag(v2f i) : COLOR
            {
                fixed4 o;
                o = i.color;
                return o;
            }
            ENDCG
        }

        Pass
        {
            Name "TEXTURE"

            Cull Back
            ZWrite On
            ZTest LEqual

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            v2f vert(appdata v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.color = v.color;
                return o;
            }

            fixed4 frag(v2f i) : COLOR
            {
                fixed4 o;
                o = tex2D(_MainTex, i.uv.xy);
                return o;
            }
            ENDCG
        }
    }
}

```

Line 41: The “Cull Front” setting tells the shader to perform a culling on the front facing vertices. It means that we will ignore all the front facing vertices in this pass. We are left with the BACK side that we want to manipulate a little.

Lines 51-53: The math of moving vertices along their normal vectors.

Line 54: Setting the vertex color to our color of choice defined in the shaders properties.

Useful Link: http://wiki.unity3d.com/index.php/Silhouette-Outlined\_Diffuse

---

# Update

another example

```
   Shader "Custom/CustomOutline" {
            Properties {
                _Color ("Color", Color) = (1,1,1,1)
                _Outline ("Outline Color", Color) = (0,0,0,1)
                _MainTex ("Albedo (RGB)", 2D) = "white" {}
                _Glossiness ("Smoothness", Range(0,1)) = 0.5
                _Size ("Outline Thickness", Float) = 1.5
            }
            SubShader {
                Tags { "RenderType"="Opaque" }
                LOD 200

                // render outline

                Pass {
                Stencil {
                    Ref 1
                    Comp NotEqual
                }

                Cull Off
                ZWrite Off

                    CGPROGRAM
                    #pragma vertex vert
                    #pragma fragment frag
                    #include "UnityCG.cginc"
                    half _Size;
                    fixed4 _Outline;
                    struct v2f {
                        float4 pos : SV_POSITION;
                    };
                    v2f vert (appdata_base v) {
                        v2f o;
                        v.vertex.xyz += v.normal * _Size;
                        o.pos = UnityObjectToClipPos (v.vertex);
                        return o;
                    }
                    half4 frag (v2f i) : SV_Target
                    {
                        return _Outline;
                    }
                    ENDCG
                }

                Tags { "RenderType"="Opaque" }
                LOD 200

                // render model

                Stencil {
                    Ref 1
                    Comp always
                    Pass replace
                }

                CGPROGRAM
                // Physically based Standard lighting model, and enable shadows on all light types
                #pragma surface surf Standard fullforwardshadows
                // Use shader model 3.0 target, to get nicer looking lighting
                #pragma target 3.0
                sampler2D _MainTex;
                struct Input {
                    float2 uv_MainTex;
                };
                half _Glossiness;
                fixed4 _Color;
                void surf (Input IN, inout SurfaceOutputStandard o) {
                    // Albedo comes from a texture tinted by color
                    fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                    o.Albedo = c.rgb;
                    // Metallic and smoothness come from slider variables
                    o.Smoothness = _Glossiness;
                    o.Alpha = c.a;
                }
                ENDCG
            }
            FallBack "Diffuse"
        }

```
> 8 votes

# Answer
The most common way I've seen this done is via a second render pass on your model. Essentially, duplicate it and flip the normals, and shove that into a vertex shader. In the shader, scale each vertex along its normal. In the pixel/fragment shader, draw black. That'll give you both external and internal outlines, like around lips, eyes, etc. This is actually a fairly cheap draw call, if nothing else it's generally cheaper than post processing the line, depending on the number of models and their complexity. Guilty Gear Xrd uses this method because it's easy to control the thickness of the line via vertex color.

The second way of doing inner lines I learned from the same game. In your UV map, align your texture along the u or v axis, particularly in areas where you want an inner line. Draw a black line along either axis, and move your UV coordinates into or out of that line to create the inner line.

See the video from GDC for a better explanation: https://www.youtube.com/watch?v=yhGjCzxJV3E
> 6 votes

# Answer
One of a great ways of doing it is to render your scene on a Framebuffer texture, to then render that texture while doing a Sobel Filtering on every pixel, which is an easy technique for edge detection. This way you can not only make the scene pixelated (setting a low resolution to the Framebuffer texture), but also have access to every pixel values to make Sobel work.
> 0 votes

---
Tags: 3d, shaders, graphics, graphics-programming
---


# Question
Title: PostFX2 Custom Effect's Y position has wrong offset ONLY in GAME camera. Scene camera is OK
I implemented raymarching in a full-screen Post FX2 custom effect.

Let's say I'm rendering a SDF sphere at world coordinates 0, 0, 0. Everything is fine in the scene camera -- if I rotate the camera in any direction, the SDF sphere retains its position at 0, 0, 0 and looks natural. For example -- if I am looking directly at the sphere and then look up by about 10 degrees, the sphere will then be naturally a bit closer to the bottom of the camera.

However, in the GAME camera, if I do that same exercise, the sphere is significantly lower. It seems like instead of being offset by the 10 or so degrees from the center, it may be about twenty. In essence, it seems like the camera's Y view direction is being doubled when rendering the pass...but it only does this for the game camera. Again, the scene camera is fine.

Here is the code:

RaymarchPostProcess.cs

```
using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.PostProcessing;

[Serializable]
public sealed class ShaderParameter : ParameterOverride<Shader> { }

[Serializable]
[PostProcess(typeof(RaymarchPostProcessRenderer), PostProcessEvent.BeforeStack, "Custom/RaymarchPostProcess")]
public sealed class RaymarchPostProcess : PostProcessEffectSettings
{
    public IntParameter maxIterations = new IntParameter { value = 64 };
    public FloatParameter maxDistance = new FloatParameter { value = 100f };
    public FloatParameter minDistance = new FloatParameter { value = 0.01f };

    public DepthTextureMode GetCameraFlags()
    {
        return DepthTextureMode.Depth; // DepthTextureMode.DepthNormals;
    }
}

public sealed class RaymarchPostProcessRenderer : PostProcessEffectRenderer<RaymarchPostProcess>
{
    Transform directionalLight;

    public override void Init()
    {
        base.Init();

        GameObject light = GameObject.FindGameObjectWithTag("MainLight");

        if (light)
            directionalLight = light.transform;
    }

    public override void Render(PostProcessRenderContext context)
    {
        Camera _cam = context.camera;

        var sheet = context.propertySheets.Get(Shader.Find("Raymarch/RaymarchHDRP"));
        sheet.properties.SetMatrix("_CamFrustum", FrustumCorners(_cam));
        sheet.properties.SetMatrix("_CamToWorld", _cam.cameraToWorldMatrix);
        sheet.properties.SetVector("_CamWorldSpace", _cam.transform.position);
        sheet.properties.SetInt("_MaxIterations", settings.maxIterations);
        sheet.properties.SetFloat("_MaxDistance", settings.maxDistance);
        sheet.properties.SetFloat("_MinDistance", settings.minDistance);

        if (directionalLight)
        {
            Vector3 position = directionalLight.forward;
            sheet.properties.SetVector("_LightDir", new Vector4(position.x, position.y, position.z, 1));
        }

        context.command.BlitFullscreenTriangle(context.source, context.destination, sheet, 0);
    }

    private Matrix4x4 FrustumCorners(Camera cam)
    {
        Transform camtr = cam.transform;

        Vector3[] frustumCorners = new Vector3[4];
        cam.CalculateFrustumCorners(new Rect(0, 0, 1, 1),
        cam.farClipPlane, cam.stereoActiveEye, frustumCorners);

        Vector3 bottomLeft = camtr.TransformVector(frustumCorners[1]);
        Vector3 topLeft = camtr.TransformVector(frustumCorners[0]);
        Vector3 bottomRight = camtr.TransformVector(frustumCorners[2]);

        Matrix4x4 frustumVectorsArray = Matrix4x4.identity;
        frustumVectorsArray.SetRow(0, bottomLeft);
        frustumVectorsArray.SetRow(1, bottomLeft + (bottomRight - bottomLeft) * 2);
        frustumVectorsArray.SetRow(2, bottomLeft + (topLeft - bottomLeft) * 2);

        return frustumVectorsArray;
    }
}

```

raymarchHDRP.shader

Shader "Raymarch/RaymarchHDRP"
{

    SubShader
    {
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            HLSLPROGRAM

            #pragma target 3.5

            #pragma vertex vert
            #pragma fragment frag

            //#include "Packages/com.unity.postprocessing/PostProcessing/Shaders/StdLib.hlsl"
            //#include "HLSLSupport.cginc"
            #include "UnityCG.cginc"

            //TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
            uniform sampler2D _MainTex;
            uniform sampler2D_float _CameraDepthTexture, sampler_CameraDepthTexture;
            half4 _MainTex_ST;
            uniform float4 _CamWorldSpace;
            uniform float4x4 _CamFrustum,  _CamToWorld;
            uniform int _MaxIterations;
            uniform float _MaxDistance;
            uniform float _MinDistance;
            uniform float3 _LightDir;
            float4 _Tint;

            uniform float4 _MainTex_TexelSize;

            struct AttributesDefault
            {
                float3 vertex : POSITION;
                half2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
             float4 vertex : SV_POSITION;
             float2 texcoord : TEXCOORD0;
             float2 texcoordStereo : TEXCOORD1;
             float4 ray : TEXCOORD2;
            };

            // Vertex manipulation
            float2 TransformTriangleVertexToUV(float2 vertex)
            {
                float2 uv = (vertex + 1.0) * 0.5;
                return uv;
            }

            v2f vert(AttributesDefault v  )
            {
                v2f o;
                v.vertex.z = 0.1;
                o.vertex = float4(v.vertex.xy, 0.0, 1.0);
                o.texcoord = TransformTriangleVertexToUV(v.vertex.xy);
                o.texcoordStereo = TransformStereoScreenSpaceTex(o.texcoord, 1.0);

                int index = (o.texcoord.x / 2) + o.texcoord.y;
                o.ray = _CamFrustum[index];

                return o;
            }

            float sdSphere(float3 position, float3 origin, float radius)
            {
                return distance(position, origin) - radius;
            }

            float distanceField(float3 p) {
                return sdSphere(p, float3(1, 0, 0), 2);
            }

            float3 getNormal(float3 p)
            {
                const float2 offset = float2(0.001, 0.0);

                float3 n = float3(
                    distanceField(p + offset.xyy) - distanceField(p - offset.xyy),
                    distanceField(p + offset.yxy) - distanceField(p - offset.yxy),
                    distanceField(p + offset.yyx) - distanceField(p - offset.yyx));

                return normalize(n);
            }

            fixed4 raymarching(float3 rayOrigin, float3 rayDirection, float depth) {
                fixed4 result = float4(1, 1, 1, 1);
                float t = 0.01; // Distance Traveled from ray origin (ro) along the ray direction (rd)

                for (int i = 0; i < _MaxIterations; i++)
                {
                    if (t > _MaxDistance || t >= depth)
                    {
                        result = float4(rayDirection, 0); // color backround from ray direction for debugging
                        break;
                    }

                    float3 p = rayOrigin + rayDirection * t;    // This is our current position
                    float d = distanceField(p); // should be a sphere at (0, 0, 0) with a radius of 1
                    if (d <= _MinDistance) // We have hit something
                    {
                        // shading
                        float3 n = getNormal(p);
                        float light = dot(-_LightDir, n);
                        result = float4(fixed3(1, 1, 1) * light, 1); // yellow sphere should be drawn at (0, 0, 0)
                        break;
                    }

                    t += d;
                }

                return result;
            }

            float4 frag(v2f i) : SV_Target
            {
                i.texcoord.y = 1 - i.texcoord.y;
                float4 col = tex2D(_MainTex, i.texcoord);
                float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoTransformScreenSpaceTex(i.texcoord));
                depth = Linear01Depth(depth);
                depth *= length(i.ray);

                float3 rayOrigin = _CamWorldSpace;
                float3 rayDirection = normalize(i.ray);
                float4 result = raymarching(rayOrigin, rayDirection, depth);

                return fixed4(col * (1.0 - result.w) + result.xyz * result.w, 1.0);
            }

            ENDHLSL
        }
    }
}
```

# Answer
Fixed. PEBCAK. It is always PEBCAK.

I had the camera transform's Y scale set to 0.33 while the X and Z were set to 1. Have a great day.

*plays lincoln park in shower*
> -1 votes

---
Tags: unity, fragment-shader, raymarching
---


# Question
Title: HLSL equivilant to "Object" data from "Texture Coordinate" node in Blender
I mocked up a shader how I wanted it with the node editor in Blender. Now I'm trying to write it in HLSL. In Blender there is a node group called "Texture Coordinate". If I use the "uv" node from the group it behaves like a normal unlit frag shader but if I use the "object" node to give coordinates to the texture, it ignores the uv data and just maps the texture like an image overlayed onto the object.

This is actually the effect I want. However, I can't find a way to replicate this in HLSL. As far as I can see I can use `TEXCOORD0` and `POSITION` as texture coordinates to produce uv mapping and world mapping respectively for a texture onto an object. Maybe what I want is object mapping?

And if it matters I'm using a generated texture

# Answer
> 0 votes
The Texture Coordinate node is commonly used for the coordinates of textures, typically used as inputs for the Vector input for texture nodes.

# Object Node

```
Shader "Blender/ObjectNode"
{
    SubShader
    {

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float4 worldPos : TEXCOORD2;
            };

            float4 _Pos;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                o.uv = v.uv;
                return o;
            }

            sampler2D _MainTex;

            fixed4 frag (v2f i) : SV_Target
            {
                return i.worldPos;
            }
            ENDCG
        }
    }
}

```

# Generated Node

you can achive generated node by Remapping world position from \[-1,1\] to \[1,0\]

```
 Shader "Blender/GeneratedNode"
{
    SubShader
    {

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float4 worldPos : TEXCOORD2;
            };

            float4 _Pos;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                o.uv = v.uv;
                return o;
            }

            sampler2D _MainTex;

            fixed4 frag (v2f i) : SV_Target
            {
                return i.worldPos*0.5+0.5;
            }
            ENDCG
        }
    }
}

```

Remapping is a way to extending coordinates:

# Resetting Position

as you now when we move object in blender we have this result:

but in unity we haven't same result:

we should reset position to fixing this problem:

```
Shader "Blender/ObjectNode"
{
    Properties
    {
        _Pos("Pos",Vector) = (0,0,0,0)
    }
    SubShader
    {

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float4 worldPos : TEXCOORD2;
            };

            float4 _Pos;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex-_Pos);
                o.uv = v.uv;
                return o;
            }

            sampler2D _MainTex;

            fixed4 frag (v2f i) : SV_Target
            {
                return i.worldPos;
            }
            ENDCG
        }
    }
}

```

then attach this script to your object to updating position:

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode]
public class ResetPos : MonoBehaviour {
    void Update () {
        GetComponent<MeshRenderer>().material.SetVector("_Pos",transform.position);
    }
}

```

---

# Update

ObjectNode

```
Shader "ObjectNode" {
    Properties {
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Lambert vertex:vert

        struct Input {
            float3 objPos;
        };

        void vert (inout appdata_full v, out Input o) {
            UNITY_INITIALIZE_OUTPUT(Input,o);
            o.objPos = v.vertex;
        }

        void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = IN.objPos;
            o.Alpha = 1;
        }
        ENDCG
    }
}

```

GeneratedNode

```
Shader "GeneratedNode" {
    Properties {
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Lambert vertex:vert

        struct Input {
            float3 objPos;
        };

        void vert (inout appdata_full v, out Input o) {
            UNITY_INITIALIZE_OUTPUT(Input,o);
            o.objPos = v.vertex;
        }

        void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = IN.objPos*0.5+0.5;
            o.Alpha = 1;
        }
        ENDCG
    }
}

```

---
Tags: shaders, hlsl, blender, fragment-shader, uv-mapping
---


# Question
Title: Is there an advantage to creating a tileset instead of multiple content items?
I'm using MonoGame to build my first game (yes, I'm new to game development). I'm trying to start by creating a 2D platformer so I want to have different "tiles" for the ground, walls, ceiling, etc.

I don't recall which tutorial I was reading, but I do know that they mentioned creating a `tileset.png` file and they gave a code sample of how to draw a specific tile from the tileset. I found a tileset on https://opengameart.org/ that I want to use for now, until I can replace the tileset.

I'm curious, is there any advantage to creating a tileset compared to creating, for example, multiple png content files?

# Answer
> 5 votes
Nowadays the most important reason to use a tilemap instead of separate pngs is just for organisation. Do you want a stage to have a different theme? Then you simply create a new tilemap, that follows the same rules as the previous one, but has a new appearence, and that's it! Compared to making so many separate new tiles, and have to point to them on each stage, it seems simpler.

Although not a big concern for small games, keep in mind that for a computer it's way easier/faster to load one big image, than multiple small ones. So it's one extra reason why putting all tiles together is better.

# Answer
> 3 votes
Here's a little experiment you can do yourself to see why using a texture atlas (or tileset) is a good idea.

The goal is to draw a checker pattern using a `white.png` texture and a `black.png` texture. The result should turn out something like this:

First, load your two textures into the game:

```
_black = Content.Load<Texture2D>("black");
_white = Content.Load<Texture2D>("white");

```

Then write the code to draw the checkerboard pattern. Something like this will do nicely:

```
var isWhite = true;

_spriteBatch.Begin(samplerState: SamplerState.PointClamp);

for (var x = 0; x < 450; x++)
{
    for (var y = 0; y < 450; y++)
    {
        if(isWhite)
            _spriteBatch.Draw(_white, new Vector2(x * _white.Width, y * _white.Height), Color.White);
        else
            _spriteBatch.Draw(_black, new Vector2(x * _black.Width, y * _black.Height), Color.White);

        isWhite = !isWhite;
    }

    isWhite = !isWhite;
}

_spriteBatch.End();

```

The point of using a checkerboard pattern like this is to force the `SpriteBatch` to continually switch textures during rendering. This simulates what's going to happen if you draw all your tiles on different `.png` files.

Next you need a way to measure the frame rate. You can make a quick and dirty FPS counter by declaring a couple of member variables in your game class like this:

```
private float _clock;
private int _frameCounter;

```

And then throw this code in your `Draw` method\**:

```
_clock += (float)gameTime.ElapsedGameTime.TotalSeconds;
_frameCounter++;

if (_clock >= 1)
{
    Console.WriteLine(_frameCounter);
    _frameCounter = 0;
    _clock = 0;
}

```

\** *Note*: this really is a quick and dirty FPS counter. Technically some of that code should be in your `Update` method but it'll do for this purpose.

When you run the game you should start seeing the frame rate spew out into the console (in Visual Studio this will be in the "Output" window).

However, all this texture switching will cause the frame rate to drop dramatically. On my computer I could only draw a 150x150 (22,500 tiles) checkerboard before my frame rate suffered. Depending on your graphics card, you might have to fiddle with the numbers to see the same effect.

Finally, you can simulate what it would be like if you used a tileset instead. Simply change the code to only use the `white.png` texture like this:

```
if(isWhite)
    _spriteBatch.Draw(_white, new Vector2(x * _white.Width, y * _white.Height), Color.White);
else
    _spriteBatch.Draw(_white, new Vector2(x * _white.Width, y * _white.Height), Color.Black);

```

Now, on my computer I can easily draw a 450x450 (202,500 tiles) checkerboard without breaking a frame rate sweat. That's a pretty significant difference.

Now that we know there's an advantage to using a tileset keep in mind that I could still render 22,500 tiles using 2 textures instead of one. Sometimes if you're only making a small game this will do just fine.

Sometimes it's okay to take some development shortcuts if it makes your life easier. It's always good to know these things but don't bend yourself backwards trying to do something if it's not really achieving anything in your game. At the end of the day, if your game runs at 60 FPS you're all good.

# Answer
> 1 votes
It comes down to performance. Tilesets are good for the engine, since it then has to only store one single path to one picture. And that picture is easily made into power of two to better be compressable and decompressable, reducing the size of your built game.

---
Tags: monogame, tilesets
---


# Question
Title: Mapping a Touchinput-device in a 3D World for VR
I have a Touch-Input device which is linked to my Unity Program and a VR Device. The Touch-Input device which is bolted somewhere BUT the position can be changed.

I can get the "2D Coordinates" X / Y from the touch input device (from 0 to 1)

For each of those 2D coordinates I also have a 3D-VR Coordinate , grabbed by a LEAP or gloves. (Those coordinates are not always the corner ones.)

Here the problem on a wonderful paint art:

So what I have is the 2d and 3d positions of my fingertip (on the touch and inside the 3d world

And what I need is the a 3d Object (for example Cube) with correct rotation and position.

Bonus points for Scale!

# Answer
```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Calibrate : MonoBehaviour
{
    public Vector2 Current_2D_TouchscreenPosition;
    public GameObject PointingFingerTip_DummyPosition;

    private Vector3 CalibrationPos_3D_1;
    private Vector3 CalibrationPos_3D_2;
    private Vector3 CalibrationPos_3D_3;

    private Vector2 CalibrationPos_2D_1;
    private Vector2 CalibrationPos_2D_2;
    private Vector2 CalibrationPos_2D_3;

    private int CalibrationIndex;
    private bool CalibrationCompleted;

    private Matrix TouchToWorldMatrix;

    public void SetCalibration(Vector3 World3DPosition, Vector2 Touch2DPosition )
    {
        //TODO: Check if values are valid!
        if (CalibrationIndex == 0)
        {
            CalibrationPos_3D_1 = World3DPosition;
            CalibrationPos_2D_1 = Current_2D_TouchscreenPosition;
            CalibrationIndex++;
        }
        else if (CalibrationIndex == 1)
        {
            CalibrationPos_3D_2 = World3DPosition;
            CalibrationPos_2D_2 = Current_2D_TouchscreenPosition;
            CalibrationIndex++;
        }
        else if (CalibrationIndex == 2)
        {
            CalibrationPos_3D_3 = World3DPosition;
            CalibrationPos_2D_3 = Current_2D_TouchscreenPosition;

            //Creating The Matrix-
            TouchToWorldMatrix = CreateTouchToWorldMatrix();
            CalibrationIndex = 0;
            CalibrationCompleted = true;
        }

    }

    Vector3 GetWorldPosition(Vector2 TouchPosition)
    {
        if (!CalibrationCompleted)
        {
            return new Vector3(0,0,0);
        }
        return MultiplyVectorWithMatrix(TouchPosition, TouchToWorldMatrix);
    }

    private Matrix CreateTouchToWorldMatrix()
    {
        //Create an empty Matrix with 4 Rows and 3 Columns
        Matrix M_LHS = new Matrix(4, 3);
        //Create another empty Matrix with 3 Rows and 3 Columns
        Matrix M_RHS = new Matrix(3, 3);

        //Fill Left Hand-Side Matrix (
        //  Row, Column
        M_LHS[0, 0] = CalibrationPos_3D_1.x;
        M_LHS[1, 0] = CalibrationPos_3D_1.y;
        M_LHS[2, 0] = CalibrationPos_3D_1.z;
        M_LHS[3, 0] = 1;

        M_LHS[0, 1] = CalibrationPos_3D_2.x;
        M_LHS[1, 1] = CalibrationPos_3D_2.y;
        M_LHS[2, 1] = CalibrationPos_3D_2.z;
        M_LHS[3, 1] = 1;

        M_LHS[0, 2] = CalibrationPos_3D_3.x;
        M_LHS[1, 2] = CalibrationPos_3D_3.y;
        M_LHS[2, 2] = CalibrationPos_3D_3.z;
        M_LHS[3, 2] = 1;

        //Fill Right Hand Side Matrix
        //  Row, Column
        M_RHS[0, 0] = CalibrationPos_2D_1.x;
        M_RHS[1, 0] = CalibrationPos_2D_1.y;
        M_RHS[2, 0] = 1;

        M_RHS[0, 1] = CalibrationPos_2D_2.x;
        M_RHS[1, 1] = CalibrationPos_2D_2.y;
        M_RHS[2, 1] = 1;

        M_RHS[0, 2] = CalibrationPos_2D_3.x;
        M_RHS[1, 2] = CalibrationPos_2D_3.y;
        M_RHS[2, 2] = 1;

        //Create a Touchscreen to Worldspace Matrix
        return M_LHS * M_RHS.Invert();
    }

    public Vector3 MultiplyVectorWithMatrix(Vector2 vector, Matrix m)
    {
        float X_Multed = (vector.x * m[0, 0]) + (m[0, 1] * vector.y) + (m[0, 2]) ;
        float Y_Multed = (vector.x * m[1, 0]) + (m[1, 1] * vector.y) + (m[1, 2]) ;
        float Z_Multed = (vector.x * m[2, 0]) + (m[2, 1] * vector.y) + (m[2, 2]) ;

        return new Vector3(X_Multed, Y_Multed, Z_Multed);

    }

}

```

Allright I managed to solve this issue.

I used this answer: https://math.stackexchange.com/questions/3108619/how-to-find-a-2d-coordinate-fields-corners-in-a-3d-coordinate-field-if-i-have-3/3109504?noredirect=1#comment6409762\_3109504

And it works.

You can basically copy-paste this script and use it. It works with creating a matrix ...
> 1 votes

---
Tags: touch, virtual-reality, augmented-reality
---


title: Set stats per tile in Unity

text:
# Question
Title: Set stats per tile in Unity
I was trying to implement a destructable tile like:

```
public class SpikeTile : Tile
{
  public int health = 3;
  public void TakeDamage(int dmg)
  {
    Debug.Log("Tile takes damage: " + dmg + ", health: " + health);
    health -= dmg;
}

```

And I will be able to remove it by using:

```
Vector3Int cell = tilemap.WorldToCell(collision_pos);

tilemap.SetTile(cell, null);

```

But it doesn't create a health value per tile! It is shared.

So I've also tried attach a GameObject with `DestructibleTile` to the above scriptable tile and:

```
DestructibleTile : MonoBehavior
{
    public int health = 3;

    // same logic
}

```

But it's also shared between all tiles! The stat is not per tile. (And after I attach the GameObject to customized Tile, it's impossible to `SetTile` to null anymore.)

Even tried create an array for all tiles to store the stats:

```
DestructibleTile : MonoBehavior
{
    public int[] health;

    // no idea how to map this to each tile
}

```

# Answer
I remember Unity guys explaining that each tile of the same type is not a separate instance. Instead the tile system visualizes literary the same tile multiple times. This is a necessary limitation to achieve decent tilemap performance.

There is a GitHub repo at Unity's profile called 2d-extras. It contains a system called GridInformation that allows assigning properties per grid position. You can find it at: https://github.com/Unity-Technologies/2d-extras
> 3 votes

# Answer
For anyone coming later for this question:

Can I use customized `Tile` to store stats per tile? The answer is, No. If you define:

```
public class MyTile : Tile
{
  public float health = 3;
}

```

The value is shared among all tiles. It's design for the performance purpose - all tiles will share same attributes and render it multiple times.

The solution I used is creating `GameObject`. Yeah, making use of `Prefab Brush` defined in 2d-extra. Following the steps:

1. Create a prefab brush
2. Attach your prefab to the dedicated brush created in 1.
3. Use this prefab brush to create gameObjects
4. Interact with the gameObjects then
> 2 votes

---
Tags: unity, tilemap
---


# Question
Title: How to calculate the price for acquisition of a mobile game
I searched long and hard thru the Game Dev community here and I didn't manage to find a good enough answer for a situation that I need help with.

Here is the deal - I've spent about a year to single-handedly develop a mobile game which is a mix between MMORPG and idle battle games. Wouldn't like to go into too much depth as to which game we are talking about and who is trying to buy it but, a company I have worked for before reached out to me with a proposal to buy the game from me so they can reap the profit from it and develop it further since they are a professional game dev company while I am a single person and I can't really reach the game's full potential as far as growth and player base goes. Now the game is pretty beneficial for me since I live in a region with a very low-income standard so the money I get from the game might not be much for many other people but for me, they are equal to about 1.5 ~ 2 monthly salaries (we are talking average salary for this country). That is about 600 Euros of pure profit after I pay for all the expenses. Of course, this number fluctuates depending on different events and sales I release and general user activity. It is a free-to-play-game so the income is mostly from microtransactions for in-game rare currency and special event item packs purchases.

Now the issue I have is that I am not sure how to set a price for the acquisition. What feels right for me would be to calculate the potential average income from the game in the next 12 months and add to this the average salary per month for a game dev of my qualifications multiplied by the number of months it took me to develop it to its released state. That would round up to about 15k euros.

When I think about it 15k euro isn't a small price to pay, but the game will pay that off in the next 1-2 years, and it might even grow much faster after they make investments for advertising and release new features and so on and so on. This means that after the second year they should be on a clean juicy profit from that deal, and that sounds good to me as well since 15k euros for me is a decent sum of money considering that the game has been running for about 14 months. And lets not forget that it has been beneficial for me for the last few months so it hasn't been always uphill.

What I need really is an advice as to is this price of around 15k Euro justified and is it a good deal for both sides, since I don't want to shoot way high and blow the acquisition, but I don't want to give the game away for a low price since it really holds a lot of potential, and it is my first fully released game.

# Answer
## A Primer on Valuing Intangible Products

> What I need really is an advice as to is this price of around 15k Euro justified

**It is not justified at all.** You're attempting to determine the market value of an **intangible product** (the mobile game) based purely upon its *cost of production*. This does not represent the true value of the product. The true value of the product is how much "the market" is willing to pay for the product. What the market is willing to pay for your product is largely dependent on **why** and **how** they value your product. Since your product is an intangible (software), this carries enormous implications contradictory to the implications of valuing a tangible (your computer, cellphone, food, furniture, etc).

The reality for intangible products is that their value is largely predicated upon the perceived value of their use or utility. In this instance, for mobile gaming that means the its ROI. The ROI for mobile games however, may be forecasted in one of 4 ways:

1. The expected ROI from selling the game: the company sells 100K units at €5 with a marketing cost of €1 euro per unit (€400K revenue: 25.6x ROI).
2. The expected ROI from microtransactions: the company implements microtransactions and receives average earnings of $10 per month from 10K regular users for a year (€400K revenue: 5.6x ROI)
3. The expected ROI from reselling the game to a larger firm: the company purchases your game for 15K, dumps 100K of development making it more robust, then resells it for 500K. (25.6x ROI)
4. The expected ROI from an IPO: the company performs an IPO and this game is popular, how will the perceived value of the game affect the value of the IPO?

Notice that for all of this, the cost of producing the intangible is small relative to the earnings. This is extremely important for intangibles because a large amount of the capital cost is usually paid upfront, either through purchase of the intangible or through the initial development of the intangible. Once the intangible is ready to ship, its packaged and distributed. Being software, the cost of distribution is incredibly small compared to the distribution cost of tangible products (compare the cost of distributing a mobile app to that of IKEA furniture). For a mobile game, you're looking at hosting costs, which are proportional to the number of active users, which in turn also drives revenue. Consequently this usually guarantees hosting costs are always a fraction of revenue. Maintenance & support costs may also be analyzed too; but, that introduces the *value added of improvements to the intangible*.

Considering you are already making €7200 (€600/mo x 12mo) profit annually you clearly already have a reliable user base on the order of hundreds to thousands depending on your actual pricing of microtransactions or the game itself. Furthermore, I cherry picked random numbers off the top of my head. Since you have been running this game and used to work for that company you know much better what numbers would be more realistic.

# The Market Value of Your Mobile Game

You described the following:

> a company I have worked for before reached out to me with a proposal to buy the game from me so they can reap the profit from it and develop it further since they are a professional game dev company while I am a single person and I can't really reach the game's full potential as far as growth and player base goes.

This sounds like a description of what you understand from what the firm described to you. This informs me of a few potential issues:

1. They are proposing to purchase all legal rights to the mobile game.
2. Their purchase is predicated upon the false assumption that you cannot reach the game's full potential in growth and player base on your own.

Combined, this suggests to me that they are intentionally trying to devalue your work and get the game for a low price. Why do I think this?

1. The predicate that you cannot reach the game's full potential on your own is blatantly false.

You can attempt to start your own game studio with initial investment coming from any of the following sources: startup incubator, Venture Capital funds, Angel Investment Funds, Private Equity investments, or business loans.

You already have a proven product with 14 months of growth and earnings to show for it. What you really need is a sound business plan and capital to action the business plan.

Alternatively you may also continue to grow it at the current rate and improve growth or start up a studio as profits allow for it.

2. They are suggesting to purchase full rights to the game. Considering you have many other options that would have you earn capital whilst retaining ownership and direction of the game, this is a red flag. If the company purchases full rights to the game, then they are empowered to cut you off immediately. This implies they have no intention to consult or work with you to determine the future of the game and are seeking full ownership of the game before ever seeing the code (which is a risky move).

Furthermore considering the nature of your question, it's obvious that they did not make an initial offer and are seeking for you to provide the initial offer. With respect to businesses purchasing software rights from an individual this reeks of abuse and deception because it forces you to start at a disadvantage (not knowing anything about how to price an acquisition for starters) and allows them to negotiate from a position of incredible strength.

# Question 2

> is it a good deal for both sides

No it is not. You are short selling yourself and the value of your game.

Talk to a lawyer and make sure you are making a sound decision for the game and your business. Selling off all rights to the game is dangerous.

Talk to a business analyst to determine the true market value of your game.

Finally consider how much the company would be willing to pay for your game if they had to compete with another firm also trying to purchase rights to the game?

That said you are attempting to value the acquisition purely upon its cost. This is erroneous. The value of an acquisition is the price at which competitors will demand the acquisition, which is dependent on their perceived value of the acquisition.
> 90 votes

# Answer
First of all, congratulations to releasing your game. Few people can claim to have created a commercially successful game all by themselves in just a year. You can be proud of that accomplishment.

Now what's that accomplishment worth?

It might help you to take a look at this from the other perspective: Imagine you had some money and you want to invest it into something which generates you revenue. You wouldn't care what it once cost to make. You only care about what return of investment it is going to generate *for you* in the future. The past development cost for that thing isn't really that relevant. It's sunken cost.

So when you want to know what your game is worth in the long-run, estimate the profits it will generate in the future and subtract the cost it will take to maintain it. That's what the game is really worth for another person. If you think that the game could generate more profit if someone would invest some marketing and/or further development into the game, then you could also do an estimation based on the income you think it *could* generate, but you need to deduct the costs this would entail.
> 25 votes

# Answer
You may want to look into the concept of annuities. The idea is that if you know what the expected income stream of an asset is, and you know what the cost of money will be, you can compute the present value of the asset.

For instance, if you expected the cost of borrowing/loaning money during that period to average, say, 6%, and if an asset were to generate a net income of 7400 euros a year for the next five years (that's approximately 600/month at 6% interest), then one can look up the present value factor in an annuity table -- which happens to be 4.212 in this example -- multiply 7400 by 4.212, and find out that the present value of this hypothetical object would be 31,253 euros.

I've made the above calculation based on a five-year lifetime for your game, though I really haven't any idea of what the profitable lifetime of a mobile game might be. If the lifetime is only two years, it's worth more around 13,500. If the lifetime is 10 years, closer to 54,500.

This should give you an idea of where to start. Of course, you need to take in not only what the asset is worth to you but also what you think the asset is worth to the company considering buying it. The former is the lowest number you should accept for the game; the latter is the highest that the company might pay for it. But at least this analysis should give you somewhere to start.

**Edit**: Adopting the model for growth.

One commenter pointed out that we may wish to take into account any projected growth or decay in your income stream. Clearly, if you thought the game were going to grow to produce millions euros of income in the next few years, neglecting this potential growth and projecting forward only its present revenue stream would be a serious mistake.

The good news is, this growth is very easy to model. The bad news is, it's very hard to predict.

To model a growth rate \\$g\\$ given a cost of money \\$r\\$, one simply calculates a combined rate \\$r^\* = (1 + r) / (1 + g) - 1 \\$. To continue the example from earlier, if you had an r of 6% and expected annual growth of, say, 2%, you would calculate \\$r^\* = (1 + .06) / (1 + .02) - 1 = .0392 = 3.92\\%\\$. For small values of r and g, you can simply subtract them for a rough estimate: 6% - 2% = 4%, which agrees well with the value we just computed.

The slight wrinkle with this method is that the assumption of constant (positive) growth is somewhat at odds with the assumption of a finite lifetime of your game. You can get around this by assuming constant growth of some amount -- say, 2% -- for a period of time followed by a decline of some other amount -- say 10% -- for the remaining expected lifetime, and the math is not terribly difficult.

The problem, though, is that predicting what the value of g should be *is* quite difficult. Professional stock market analysts struggle to make exactly this determination on a regular basis, and they get it wrong just as often as they get it right. But if you have a good sense of the rate at which income from your game will grow or decline over the next few years, it may be worth incorporating that knowledge into your model as well -- especially if the growth rate is likely to be significant.
> 11 votes

# Answer
I was in a similar situation a number of years ago when I sold some of my software assets. There a lot of good answers here about income and ROI, but I'd like to approach the question from another angle: what do you enjoy doing?

Some of the answers talk about how you could realize your potential by coming up with a business plan and getting investors. But what happens after that? Do you have skills in sales and marketing? Do you know how to advertise and use social media effectively? If so, then that's great. Or would you want to hire a marketing person? You could use investor's money to pay them, but now you'd become a manager to make sure they did their job effectively.

Or are you like me and you're a developer and you have no interest in sales and marketing or management? And there's nothing wrong with that. :)

In this case, it might be better to sell your game for a price both you and the buyer are happy with. Then you can either continue developing the game for them (if they want to hire you) or you can work on a new game. And since you have the skills to make a game that another company wants to buy, you can repeat the process: make a game, sell it, make another game, sell that one, and so on.
> 5 votes

# Answer
## You're selling a business, not a game

For starters, this is an economics question - the specifics of the business don't matter *that* much. Business valuation is tricky, but the general framework to think about consists of two numbers - one is the "pure profit after I pay for all the expenses" that you showed, and the other is a multiplier (i.e. "how many years/months of profit should this cost) which is determined mostly by (a) the risks/uncertainty of that future income and (b) the expected longevity of that future income - either growth prospects (a key thing for startup valuation) or the time until the cash cow dies (a key thing for particular products, which often decline until obsolete).

You can, with some effort, look for "standard multipliers" in your domain - the shared consensus understanding of approximately how much months of profit a mobile game is worth. It seems that they're offering to buy the game for approximately 2 years of profit. IMHO for a semi-stable online business (and one that's expected to decline in the long run! game businesses do die out as new ones come out) that's somewhat reasonable. Perhaps you could argue with them (if you're still seeing growth that you can show in solid metrics) that you'd need 2.5 or 3 years of current profit; a lot is simply determined by particular wants of the parties, random factors and negotiation, but certainly the offer isn't outrageous - it would seem unreasonable to sell such a business with a multiplier of 1 year or 6 years of profits, but something within 1.5-3 (depending on specifics) seems appropriate.
> 4 votes

# Answer
There's some really good answers here already, but here are a few additional points to consider that I don't think have been mentioned already:

* Have a figure in mind, but ask them to "make you an offer". You then have some idea of their potential starting point, and it may be considerably higher than yours. If you start the negotiation with a low figure, they have no reason to subsequently raise it.
* Consider retaining partial ownership or forming a partnership with them as part of the deal. For example a % of future profits. It may well be in their interests to retain your input as a consultant too. You're the creator of this business, and if the game was to keep growing and generating large sums of money, would you feel happy about being bought off with a relatively small sum?
> 4 votes

---
Tags: marketing, business
---


# Question
Title: How to move bezier curve points along circle to form a symmetric curve at center
From the image below, A is an open bezier curve with it's points positioned to represent a circle. AP3 and AP1 have the same position. From B, How can I move the points (AP1 and AP3 along the bigger circle of radius r whiles the CP's reduce in length as CP1 and CP4 also rotate) till they form a symmetric bezier curve at the center of the bigger circle marked as the red curve?

# Answer
> 1 votes
To keep things simple & consistent, let's stick with circular arcs throughout.

We'll have our first circle with radius \\$r\_1\\$, shown in red below.

Then we'll use a second radius \\$r\_2\\$ to define the new positions of our endpoints as the curve swings open by an angle \\$\alpha\\$, shown on the green circle below.

Then we'll draw a third circle, through our moved anchor points \\$AP\_1\\$, \\$AP\_3\\$ and the one we left stationary \\$AP\_2\\$, shown in blue below. This gives us a unique arc to follow.

Since we already know how to trace a circular arc with a cubic Bézier curve, once we find this circle we'll be able to draw the arc along it trivially. So I'll focus on finding the parameters of the circle below:

Let's get down to placing the points. For simplicity I'm going to assume that the fixed point is always at the rightmost edge of the red circle, and that the centers & radii of the circles \\$ \vec C\_1, r\_1, \vec C\_2,r\_2\\$ are known, along with the angle \\$ \alpha \> 0\\$ you want to open the initial curve by. (For \\$\alpha = 0\\$, we just draw the original curve as in your previous question)

Now, we know our top anchor point is at...

$$\vec {AP\_1} = \vec C\_2 + r\_2 \cdot \left(-\cos \alpha, \sin \alpha \right)$$

and our fixed anchor point is at...

$$\vec {AP\_2} = \vec C\_1 + \left( r\_1, 0 \right)$$

Then the midpoint of the line joining these is at...

$$ \vec M = \frac 1 2 \cdot \left( \vec {AP\_1} + \vec {AP\_2} \right)$$

A perpendicular \\$\vec p\\$ from this midpoint will point the way to our third center \\$\vec C\_3\\$

$$ \vec p = \left( -M\_y, M\_x - {AP\_2}\_x \right)$$

(If \\$p\_y = 0\\$ then we've opened the curve all the way to a straight line, so just draw a straight line from \\$AP\_1\\$ to \\$AP\_3\\$ and you're done)

We can scale this by a factor \\$t\\$ to reach the horizontal axis and locate our center:

$$t = \frac {{AP\_2}\_y - M\_y} {p\_y}$$

$$\vec C\_3 = \vec M + t \cdot \vec p$$

$$r\_3 = {AP\_2}\_x - {C\_3}\_x$$

And now we can find our angle \\$\theta\\$ with:

$$\theta = atan2(\vec {AP\_1} - \vec C\_3)$$

(Just note that in many APIs, the first argument of `atan2` is `y` not `x`, so be sure you put the components in the right order)

Now we have a center (\\$\vec C\_3\\$), a radius (\\$r\_3\\$), a start angle (0), and an end angle (\\$\theta\\$), so we can draw a cubic Bézier curve along this circular arc using the technique described in my earlier answer.

For the lower half, just flip the y coordinates along the horizontal.

---

Here's an animation of this method in action:

With a little attention to our start points, we can even make this work starting from a less-than-full circle:

Here's the code I used:

```
// Buffer for our final spline's anchor & control points.
Vector2[] _bezierPoints = new Vector2[7];

// How much of the inner circle should we start with?
[Range(0,180)]
public float circleCoverageDegrees= 180f;

// Size & center of our inner circle (red).
public float firstRadius = 1.0f;
public Vector2 firstCenter;

// Size & center of our second circle (green).
public float secondRadius = 2.0f;
Vector2 _secondCenter;  // Computed from radius & coverage.

// How far should we swing the anchor points out around the green circle?
[Range(0, 180)]
public float swingOutDegrees = 0f;

// Size & center of our third circle (blue).
Vector2 _thirdCenter;
float _thirdRadius;

// Used to mark the line from the second circle's center
// to our inner anchor points before we've swung them outward.
Vector2 _secondToInnerStart;

void OnValidate()
{
    if (secondRadius < firstRadius)
        secondRadius = firstRadius;

    // Place the anchor points of the original circle.
    // (For now, I assume its center is (0, 0), and add it as an offset later)
    Vector2 innerArcStart = PointOnCircle(firstRadius, circleCoverageDegrees);
    Vector2 fixedAnchor = PointOnCircle(firstRadius, 0f);

    // Place the second center so the green circle passes through the endpoints.
    float horizontalDeviation = Mathf.Sqrt(secondRadius * secondRadius - innerArcStart.y * innerArcStart.y);
    _secondCenter = new Vector2(innerArcStart.x + horizontalDeviation, 0f);

    _secondToInnerStart = innerArcStart - _secondCenter;

    float startDegrees = Mathf.Approximately(_secondToInnerStart.x, 0) ? 90f
                      : Mathf.Rad2Deg * Mathf.Atan(-_secondToInnerStart.y / _secondToInnerStart.x);

    // Swing out our anchor points along the green circle.
    Vector2 finalArcStart = _secondCenter + PointOnCircle(secondRadius, 180 - startDegrees - swingOutDegrees);

    // Find the center of the blue circle joining these anchors.
    Vector2 midpoint = (finalArcStart + fixedAnchor) / 2f;
    Vector2 perpendicular = new Vector2(-midpoint.y, midpoint.x - fixedAnchor.x);

    // If they're in a vertical line, abort and just draw a straight line.
    if(Mathf.Approximately(perpendicular.y, 0f)) {
        _thirdRadius = float.PositiveInfinity;

        _bezierPoints[0] = firstCenter + finalArcStart;
        _bezierPoints[3] = firstCenter + fixedAnchor;
        _bezierPoints[6] = 2 * firstCenter - finalArcStart;

        _bezierPoints[1] = Vector2.Lerp(_bezierPoints[0], _bezierPoints[3], 1f / 3f);
        _bezierPoints[2] = Vector2.Lerp(_bezierPoints[0], _bezierPoints[3], 2f / 3f);
        _bezierPoints[4] = Vector2.Lerp(_bezierPoints[3], _bezierPoints[6], 1f / 3f);
        _bezierPoints[5] = Vector2.Lerp(_bezierPoints[3], _bezierPoints[6], 2f / 3f);
        return;
    }

    // Phew, we have a non-infinite circle! Place its center & radius.
    float t = -midpoint.y / perpendicular.y;

    _thirdCenter = new Vector2(midpoint.x + t * perpendicular.x, 0f);
    _thirdRadius = Mathf.Abs(_thirdCenter.x - fixedAnchor.x);

    // Find the angle of the endpoints around this blue circle.
    Vector2 thirdToFinalStart = finalArcStart - _thirdCenter;
    float angle = Mathf.Rad2Deg * Mathf.Atan2(thirdToFinalStart.y, thirdToFinalStart.x);

    // Handle reversing concavity correctly.
    float pivot = _thirdCenter.x < fixedAnchor.x ? 0 : 180;

    // Populate our Bezier curve buffers using code from previous answer.
    BezierCircle(_thirdCenter, _thirdRadius, angle, pivot, _bezierPoints, 0);
    BezierCircle(_thirdCenter, _thirdRadius, pivot, 2 * pivot - angle, _bezierPoints, 3);
}

// Convenience method for plotting a point in polar coordinates.
static Vector2 PointOnCircle( float radius, float angleDegrees) {
    float angleRadians = angleDegrees * Mathf.Deg2Rad;
    return radius * new Vector2(Mathf.Cos(angleRadians), Mathf.Sin(angleRadians));
}

```

---
Tags: unity, mathematics, curves
---


# Question
Title: What does all the positioning properties of sprites in PIXI.js v4 do?
What does all the position properties and functions on a pixi.js sprite / DisplayObject actually do? You can access `sprite.x`, `sprite.width`, `sprite.getBounds()`, `sprite.toLocal()`, `sprite.toGlobal()`, `sprite.getGlobalPosition()`, `sprite.getLocalBounds()`.

And how are they affected by scale, pivot, position and parent properties?

---

I was very confused with all the various ways to get positioning from PIXI.js sprites, and didn't find the documentation helpful, so I created an example, to help me get an overview (at the end of this post).

This example also creates a camera, that can be used to center the view on selectable sprites.

```
// Size of the rectangles
const rectSize = 10;
// Rotation of the rotated rectangle
const rotation = 45;
// Zoom level of the camera, higher is closer
const zoomLevel = 2;
// Resolution of the app
const resolution = 1;

// Create the pixi app
const app = new PIXI.Application({
  width: 100,
  height: 100,
  backgroundColor: 0x000000,
  interactive: true,
  resolution: resolution
});
// HTML elements
const $body = $('body');
const $pixi = $('#pixi');
const $info = $('#info').find('tbody');

$pixi.append(app.view);

// Camera controls what we see
const camera = new PIXI.Container();
camera.scale.set(zoomLevel, zoomLevel);
app.stage.addChild(camera);

// Origin is the stage position - never move the stage
const origin = app.stage.position;

// Create some sprites
const rect = new PIXI.Graphics();
rect.beginFill(0xffffff);
rect.drawRect(0, 0, rectSize, rectSize);
const texture = app.renderer.generateTexture(rect);
const zeroedChild = PIXI.Sprite.from(texture);

const positionedChild = PIXI.Sprite.from(texture);
positionedChild.tint = 0xd83131
positionedChild.position.set(rectSize, rectSize);

const rotatedChild = PIXI.Sprite.from(texture);
rotatedChild.tint = 0x34d839;
rotatedChild.position.set(rectSize, rectSize);
rotatedChild.rotation = rotation * Math.PI / 180;

const scaledChild = PIXI.Sprite.from(texture);
scaledChild.tint = 0x4065d6;
scaledChild.position.set(rectSize, rectSize);
scaledChild.scale.set(2, 2);

const pivotedChild = PIXI.Sprite.from(texture);
pivotedChild.tint = 0xb637d6;
pivotedChild.position.set(rectSize, rectSize);
pivotedChild.pivot.set(pivotedChild.width / 2, pivotedChild.height / 2);

// Add all sprites to the camera
camera.addChild(zeroedChild, positionedChild, rotatedChild, scaledChild, pivotedChild);

updateInfo();

function updateInfo() {
  $info.html('');
  $info.append(info('Camera', camera, origin));
  $info.append(info('Zeroed Child', zeroedChild, origin));
  $info.append(info('Positioned Child', positionedChild, origin));
  $info.append(info(`Rotated Child (${rotation})`, rotatedChild, origin));
  $info.append(info('Scaled Child (2)', scaledChild, origin));
  $info.append(info('Pivoted Child (center)', pivotedChild, origin));
}

function info(name, sprite, origin) {
  const $row = $('<tr></tr>');
  if (sprite.parent) {
    if (!sprite.originalTint) {
      sprite.originalTint = sprite.tint;
    }

    $row.on('mouseenter', () => {
      const parent = sprite.parent;
      sprite.tint = 0xf4ff2b;
      parent.removeChild(sprite);
      parent.addChild(sprite);
    });
    $row.on('mouseleave', () => {
      sprite.tint = sprite.originalTint;
    });
    $row.on('click', () => {
      centerOn(sprite);
      sprite.parent.children.forEach((child) => {
        child.tint = child.originalTint;
      });
      sprite.tint = 0xf4ff2b;
    })
  }
  $row.append(`<td><b>${name}</b></td>`);
  $row.append(`<td>(${r(sprite.x)}, ${r(sprite.y)})</td>`);
  $row.append(`<td>(${r(sprite.toLocal(origin).x)}, ${r(sprite.toLocal(origin).y)})</td>`);
  $row.append(`<td>(${r(sprite.toGlobal(origin).x)}, ${r(sprite.toGlobal(origin).y)})</td/>`);
  $row.append(`<td>(${r(sprite.getGlobalPosition().x)}, ${r(sprite.getGlobalPosition().y)})</td>`);
  $row.append(`<td> (${r(sprite.scale.x)}, ${r(sprite.scale.y)})</td>`);
  $row.append(`<td>(${r(sprite.width)}, ${r(sprite.height)})</td>`);
  $row.append(`<td>(${r(sprite.getBounds().x)}, ${r(sprite.getBounds().y)}) | w: ${r(sprite.getBounds().width)}, h: ${r(sprite.getBounds().height)})</td>`);
  $row.append(`<td>(${r(sprite.getLocalBounds().x)}, ${r(sprite.getLocalBounds().y)}) | (${r(sprite.getLocalBounds().width)}, ${r(sprite.getLocalBounds().height)})</td></tr>`);

  return $row;
}

function r(n) {
  return Math.round(n * 100) / 100;
}

// Centers the camera on the given sprite
function centerOn(sprite) {
  if (sprite === camera) {
    camera.position.set(0, 0)
    updateInfo();
    return;
  }

 // Find the center of the renderer = canvas
  const centerRendererX = (app.renderer.width / resolution) / 2;
  const centerRendererY = (app.renderer.height / resolution) / 2;
  // Get the bounds of the sprite
  const bounds = sprite.getBounds();
  // Get the current position of the camera
  const cPos = camera.getGlobalPosition();
  // The bounds of the sprite is affected by the position of the camera (parent)
  // Subtract the camera position from the sprite position to put the sprite at it's original location
  // Then center it in the renderer/canvas, and find the middle of the sprite
  const x = centerRendererX - ((bounds.x - cPos.x) + bounds.width / 2);
  const y = centerRendererY - ((bounds.y - cPos.y) + bounds.height / 2);

  camera.position.set(x, y);
  updateInfo();
}
```

```
html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  font-size: 13px;
  font-family: courier;
}

b {
  display: block;
  font-size: 15px;
  width: 100%;
  text-align: center;
}

#info {
  width: 100%;
  border: 1px solid #fff;
  color: #fff;
  background-color: #000;
}

#info td {
  border: 1px solid #fff;
}

#info tr:hover {
  cursor: default;
  background-color: #252525;
  color: red !important;
}
```

```
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.7.0/pixi.min.js"></script>
<table id="info">
  <thead>
    <tr>
      <th>Name</th>
      <th>(x, y)</th>
      <th>toLocal(stage)</th>
      <th>toGlobal(stage)</th>
      <th>getGlobalPosition()</th>
      <th>scale</th>
      <th>width/height</th>
      <th>getBounds()</th>
      <th>getLocalBounds()</th>
    </tr>
  </thead>
  <tbody></tbody>
</table>

<div id="pixi">

</div>
```

(Source)

# Answer
In PIXI.js v4:

I found the documentation unhelpful as there are subtleties to getting a global position when there are local transformations like `.pivot` and `.rotations`. I found that the easiest way to get a global position when you only want *some* local transformations is to do something like.

```
let oldRot = sprite.rotation;
sprite.rotation = 0;
let globalPosition = this.toGlobal(new PIXI.Point(0,0));
sprite.rotation = oldRot;

```

This will unapply the `.rotation` transformation when the matrix is rebuilt in `toGlobal` allowing you to get a position only affect by `.pivot`
> 3 votes

---
Tags: javascript, pixi.js
---


# Question
Title: How can I display only the new state of the grid?
I am making a console based snake game. I am able to move the snake using grids that show up successively on the console. I want to animate the snake using always the same grid.

```
    static void Main(string[] args)
    {
        char[,] board = new char[17, 17];
        int count = 5;
        for (int i = 0; i <= 16;             {
            for (int j = 0; j <= 16; j++)
            {
                board[i, j] = '.';
            }
        }
        while (count < 11)
        {
            board[8, count] = '*';
            board[8, count + 1] = '*';
            board[8, count + 2] = '*';
            board[8, count + 3] = '*';
            board[8, count + 4] = '*';
            board[8, count + 5] = '*';
            board[8, count + 6] = '*';

            for (int i = 0; i <= 16; i++)
            {
                for (int j = 0; j <= 16; j++)
                {
                    Console.Write(board[i, j]);
                }
                Console.WriteLine();
            }
            count++;
        }
    }

```

# Answer
> 2 votes
Assuming I understood your question correctly, simply call `Console.Clear()` before you draw your grid. This will clear the console of all text so when you draw your grid it will always be at the top.

# Answer
> 0 votes
I have made some progress. I have got the snake to move to the right and to move down.

```
        static void Main(string[] args)
    {
        const int board_size = 17;
        char[,] board = new char[board_size, board_size];
        int horizontal = 5, vertical = 8, count = 0;

        for (int i = 0; i < board_size; i++)
        {
            for (int j = 0; j < board_size; j++)
            {
                board[i, j] = '.';
            }
        }

        void draw_board()
        {
            for (int i = 0; i < board_size; i++)
            {
                for (int j = 0; j < board_size; j++)
                {
                    Console.Write(board[i, j]);
                }
                Console.WriteLine();
            }
        }

        while (count < 12)
        {
            if (count >= 0 && count < 6)
            {
                board[vertical, horizontal] = '*';
                board[vertical, horizontal + 1] = '*';
                board[vertical, horizontal + 2] = '*';
                board[vertical, horizontal + 3] = '*';
                board[vertical, horizontal + 4] = '*';
                board[vertical, horizontal + 5] = '*';
                board[vertical, horizontal + 6] = '*';

                draw_board();

                horizontal++;
            }

            if (count > 5 && count < 12)
            {
                board[vertical, horizontal] = '*';
                board[vertical+1, horizontal] = '*';
                board[vertical+2, horizontal] = '*';
                board[vertical+3, horizontal] = '*';
                board[vertical+4, horizontal] = '*';
                board[vertical+5, horizontal] = '*';
                board[vertical+6, horizontal] = '*';

                draw_board();

                vertical++;
            }

            count++;

            System.Threading.Thread.Sleep(1000);
            Console.Clear();
        }
    }

```

---
Tags: c#, text-based
---


# Question
Title: Why are my waves not spawning as expected?
Hey guys so here's an outline of my problem using a basic 3-step approach

**The Problem Defined** Waves 1-22 should spawn in order with the correct paths and enemy prefabs. However, Waves 1-4 only spawn and repeat on a loop. https://www.youtube.com/watch?v=p0HZ\_qo4SxU

**Possible Causes** I think the issue possibly lies within my enemyspawner.cs script but it could also potentially lie within my level.cs and waveconfig.cs scripts. Oddly enough this seems to also be an issue with the original source code as well. I made several copies of the prefabs, gave them unique paths and waves and changed the new enemy prefabs to different colors to test it and the same result happens. https://www.youtube.com/watch?v=8zr7CVjty6k

**The needed solution** I need all 22 waves to re-spawn in order correctly as only having 4 waves repeat is very repetitive and boring.

Here is my specific code for enemyspawner:

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemySpawner : MonoBehaviour {

    [SerializeField] List<WaveConfig> waveConfigs;
    [SerializeField] int startingWave = 0;
    [SerializeField] bool looping = false;

    IEnumerator Start()
    {
        do
        {
            yield return StartCoroutine(SpawnAllWaves());
        }
        while (looping);
    }

    private IEnumerator SpawnAllWaves()
    {
        for (int waveIndex = startingWave; waveIndex < waveConfigs.Count; waveIndex++)
        {
            var currentWave = waveConfigs[waveIndex];
            yield return StartCoroutine(SpawnAllEnemiesInWave(currentWave));
        }
    }

    private IEnumerator SpawnAllEnemiesInWave(WaveConfig waveConfig)
    {
        for (int enemyCount = 0; enemyCount < waveConfig.GetNumberOfEnemies(); enemyCount++)
        {
            var newEnemy = Instantiate(
                waveConfig.GetEnemyPrefab(),
                waveConfig.GetWaypoints()[0].transform.position,
                Quaternion.identity);
            newEnemy.GetComponent<EnemyPathing>().SetWaveConfig(waveConfig);
            yield return new WaitForSeconds(waveConfig.GetTimeBetweenSpawns());
        }
    }
}

```

Here is my specific code for waveconfig:

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "Enemy Wave Config")]
public class WaveConfig : ScriptableObject
{

    [SerializeField] GameObject enemyPrefab;
    [SerializeField] GameObject pathPrefab;
    [SerializeField] float timeBetweenSpawns = 0.5f;
    [SerializeField] float spawnRandomFactor = 0.3f;
    [SerializeField] int numberOfEnemies = 5;
    [SerializeField] float moveSpeed = 2f;

    public GameObject GetEnemyPrefab() { return enemyPrefab; }

    public List<Transform> GetWaypoints()
    {
        var waveWaypoints = new List<Transform>();
        foreach (Transform child in pathPrefab.transform)
        {
            waveWaypoints.Add(child);
        }
        return waveWaypoints;
    }

    public float GetTimeBetweenSpawns() { return timeBetweenSpawns; }

    public float GetSpawnRandomFactor() { return spawnRandomFactor; }

    public int GetNumberOfEnemies() { return numberOfEnemies; }

    public float GetMoveSpeed() { return moveSpeed; }

}

```

Here is my specific code for Level:

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class Level : MonoBehaviour
{

    [SerializeField] float delayInSeconds = 2f;

    public void LoadStartMenu()
    {
        SceneManager.LoadScene(0);
    }

    public void LoadGame()
    {
        SceneManager.LoadScene("Game");
        FindObjectOfType<GameSession>().ResetGame();
    }

    public void LoadGameOver()
    {
        StartCoroutine(WaitAndLoad());
    }

    IEnumerator WaitAndLoad()
    {
        yield return new WaitForSeconds(delayInSeconds);
        SceneManager.LoadScene("Game Over");
    }

    public void QuitGame()
    {
        Application.Quit();
    }

}

```

# Answer
> 1 votes
The following has nothing to do with the question, but I couldn't format the code in a comment.

You should look into using properties for your fields. They greatly reduce your complexity and are a good shortcut. As an example:

```
[SerializeField] float timeBetweenSpawns = 0.5f;
public float GetTimeBetweenSpawns() { return timeBetweenSpawns; }

```

is identical to

```
public float TimeBetweenSpawns {get; private set;}
// This creates a property on the object that can be accessed publicly
// but only set within its class

```

This prevents you from having to write out manual getters and setters for common methods, and prevents you from having to do bad design, like telling unity to serialize a private field.

# Answer
> 1 votes
Hey guys so the issue happened to be that my enemy spawner prefab became corrupted somehow and after I replaced it with my saved source code, everything is working correctly, and oddly enough the master code from the course I built the game from had the same issue but if you are following along to the course just make sure to have all your needed prefabs in the game scene.

---
Tags: unity, c#
---


# Question
Title: Technical term for the border that appears around the screen, usually in response to low health?
This had a strange term but I can't remember what it's called and it's difficult to search for.

# Answer
> 5 votes
At our studio (Ubisoft Toronto) we usually call it a (low) health vignette.

A vignette in photography & film refers to an effect around the edges of the frame (usually a darkening or defocus) like this:

By attaching modifiers to it like "low health" or "super" etc. we express "that effect at the edges of your screen when you're in the \______ state"

Here are some sources that also call it a health vignette:

If it's particularly intrusive into the middle of the frame, we call it "strawberry jam" ;)

---
Tags: gui, terminology
---


# Question
Title: How to ease toward a rotation limit, instead of stopping abruptly?
I rotate my camera using a framerate-independent exponential ease-out blend like so:

```
    _x += Input.GetAxis("Mouse X") * xSpeed;
    float target = 0f; //I want to blend towards 0
    float sharpness = 0.05f; //the smaller this value, the longer it takes to settle down to the target value
    float referenceFramerate = 90f;//the approximate framerate on my developer machine
    float blend = 1f - Mathf.Pow(1f - sharpness, Time.deltaTime * referenceFramerate);
    _x = Mathf.Lerp(_x, target, blend);

```

This works fine.

Now my camera should be clipped at a certain rotation yaw.

The new camera rotation yaw is calculated like this:

```
    _CurrentYaw += _x * Mathf.Abs(_CameraDefaultPos.z);
    if (_CurrentYaw > 160f)
    {
       _CurrentYaw = 160f;
    }
    else if (_CurrentYaw < -120f)
    {
       _CurrentYaw = -120f;
    }

```

This clipping part of my code makes the camera stop abruptly at the maximum.

How could the above Mathf.Lerp function be adopted to make it so that the \_x value would be damped more quickly when going towards the rotation limit?

# Answer
Here's one way you can tackle it: computing how far you are from the center of the allowed range, and applying a braking multiplier the closer you are to the edge.

```
public class LimitedCameraYaw : MonoBehaviour
{
    const float referenceFramerate = 30.0f;

    public float yawCenter = 20;
    public float yawRange = 140;

    public float yawInputFalloff = 0.01f;
    public float yawSpeed = 60.0f;

    float _currentYaw;
    float _yawRate;

    void Update() {
        // Fade old input before capturing new, so we don't dull the freshest data.
        float blend = Mathf.Pow(1.0f - yawInputFalloff, referenceFramerate * Time.deltaTime);
        // A Lerp toward zero is just the same as a multiplication by the complement of the blend factor.
        _yawRate *= blend;

        // Accelerate by mouse movement over the past frame.
        // (May need adjustment for display resolution).
        _yawRate += Input.GetAxis("Mouse X");

        float yawDelta = yawSpeed * _yawRate * Time.deltaTime;

        float offCenter = _currentYaw - yawCenter;

        // If we're moving away from the center, slow down as we approach the edge.
        if (yawDelta * offCenter > 0) {
            float extremity = offCenter / yawRange;
            yawDelta *= 1.0f - extremity * extremity;
        }

        // Ensure we never overshoot the allowed range.
        _currentYaw = Mathf.Clamp(_currentYaw + yawDelta,
                                  yawCenter - yawRange,
                                  yawCenter + yawRange);

        transform.eulerAngles = Vector3.up * _currentYaw;
    }
}

```
> 1 votes

---
Tags: unity, c#, easing
---


# Question
Title: Wind-blown fire particle effect from scratch
I want to create an effect of fire and be able to give it a variable amount of "wind" to make it blow to the side. I don't want the particles to just curve off to the side, but to flow through the air semi-realistically, similar to the effect of the fire in this video.

I'm assuming this would involve using trigonometric functions to achieve a "wavy" pattern?

My engine is completely from scratch and built on top of Slick2D / LWJGL. I already have a particle system in place that I implemented for everything from simple blood splatter effects to projectiles.

Simple effects like a "spray" or blood splatter are easy, but I don't know how to make something more complicated. I'm not really sure how to make this look like anything but a random burst of small squares or poorly drawn fire sprites.

# Answer
An effect like the one you show is actually pretty simple to code.

Create a class `Ember` that sits at one `(x,y)` position and randomly spawns 1-pixel particles that move upward (either accelerate upward or move at constant speed as your image). Push each particle into `ember.particleList` to be used for updates / ticks. Give a 50% chance to spawn new particle each tick.

Next step is moving these particles that are spawned. Every frame (again), make sure that a particle moves one pixel upward and reduces its alpha by some fixed amount. You should now see the particles emerging from the baseline and moving straight up (y), fading alpha, then disappearing.

Next step is wind. You'll need to impart some sideways velocity (x) to all particles already in the air, i.e. all those in `ember.list`. You have a wind velocity that is a simple `float`, either positive or negative. Every frame you adjust it by some amount depending on the wind direction shift between -1.0 and +1.0. Say `windspeed` currently equals -1.0, and your currently calculated `windshift` is `0.2`. `-1.0 + 0.2 = -0.8`. The `windshift` should not change too suddenly, by the way, or it will not look good. In nature, wind accelerates and decelerates, like a car. Notice how, because a particle can only shift up to a max of 1.0 pixels left or right in a frame, those particles nearest the top of the flame (the eldest), are those that can have shifted the most.

Now just set up multiple embers running across the screen, and you've got a flame field.
> 4 votes

---
Tags: lwjgl, slick, particles, graphic-effects
---


title: Avoid useless copies of buffers

text:
# Question
Title: Avoid useless copies of buffers
The other day I was looking at a opensource engine, basically it was uploading the image from a file to a RAM buffer adding some decoding while streaming (I assume this is done "in-cache" so I can't count the decoding as an extra copy), then the buffer was feeded to `glTexImage2D`.

According to GL specifications, `glTexImage2D` is free to keep a in-RAM copy of the image and wait for the best moment to upload it to the GPU.

So basically we have

* From disk to RAM
* From RAM to RAM
* From RAM to GPU

Thos are basically 4-5 BUS runs x Textures Size in megabytes bandwith payload

3 copies of the same data.

Isn't there anyway to reduce the copies to

* From disk to RAM
* from RAM to GPU

Or even

* From disk to GPU

?

(Assuming hard-disk already have data in the correct memory layout and hence no decoding is necessary).

# Answer
> 5 votes
The answer is using a PBO, Pixel Buffer Object.

You map a opengl buffer and put the image data into there. Then unmap and bind that buffer to `GL_PIXEL_UNPACK_BUFFER` and call `glTexImage2D` with the `data` parameter set to `(void* )0`. This makes `glTexImage2D` use the buffer as the data source instead of the application memory. The `data` parameter is the offset into the buffer.

Because opengl was in charge of allocating that buffer and it's not mapped anymore it does not need to make a copy of the buffer.

---
Tags: optimization
---


title: Mesh rendering performance optimisation

text:
# Question
Title: Mesh rendering performance optimisation
I'm working on a libgdx implementation of mesh terrain and running into some performance issues.

The terrain is represented by a number of mesh tiles, each mesh is made of vertices laid onto a 2D plane.

The implementation of the meshes is done via libgdx Mesh, each of which is cached after its initial generation. I use GL3.0 and therefore the vertices are handled via `VertexBufferObjectWithVAO` which as I understand it should allow GPU caching. Meshes are indexed.

Aiming to optimise performance, I have tried to increase the number of vertices in each mesh (while keeping the same overall amount of vertices) but weirdly the performance gets worse rather than improving.

**Question 1**: any possible reasons why given the same total number of vertices the scenario with lower amount of meshes (#3 below) is slower than the scenarios with higher number of meshes?

**Question 2**: based on the OPENGL pipeline summarised below is it correct to assume that VBOs are being transferred to the GPU once and then drawn via GPU memory reference?

**Performance comparison**

1. 1,600 meshes * 3,042 vert (4.8M vertices) -\> 131 FPS
2. 625 meshes * 11,250 vert (4.5M vertices) -\> 132 FPS
3. 100 meshes * 45,000 vert (4.5M vertices) -\> 113 FPS

**Hardware Details**

GTX660 2GB Memory Utilisation during test 70% in all scenarios. Vertex allocation memory impact seems to be negligible compared to textures.

**OPENGL pipeline**

From API TRACE, this is the frame life-cycle in summary

*mesh generation (one off)*

```
glGenBuffers()
glGenVertexArrays()

```

*render (every frame)*

```
glClear(GL_COLOR_BUFFER_BIT)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glUseProgram(...)
glUniformMatrix4fv(...)
glUniform1f(...)
glActiveTexture(...)
glBindTexture(...)
...
glBindVertexArray(...)
glBindBuffer(...)
glDrawElements(...)
[for each mesh]

```

\*edited to clarify that I have tried to group the vertices into less amount of meshes to reduce number of draw calls

\**edited to provide more data and streamline questions.

# Answer
There could be a number of reasons why performance is sluggish, I'll mention some of which I think are the biggest ones, based on your question:

* Bigger mesh does **not** mean less performance-intensive. Assuming a mesh is clearly visible by the camera (not cut-off) then the smallest it is, the less pixels have to calculate how to draw it (in shaders).
* The idea on VBO is that you give a mesh to the GPU, and then you can draw that mesh multiple times on different places. In your case that you are drawing a terrain, if it's anything similar to games like minecraft, you'd only need to upload to the GPU a few different meshes, and then you'd be able to draw massive amounts of land with them.
* A classic trap new people fall into is that they think the whole virtual world is always active and being drawn. That is not the case. No matter how big your map is, you'd almost never draw all of it. Divine it into chunks, load only the ones closest to the player. If the player is approaching the edge of a chunk, load the next one. With this method you can make "infinite" worlds without performance suffering.
> 1 votes

---
Tags: opengl, libgdx, mesh
---


# Question
Title: Correctly get size from Canvas UI element on Unity
Normally when anchors are on the same position, we can use `.sizeDelta` or `.rect.width/height` from `RectTransform`, but if the anchor are stretched, both of them returns negative values:

Which in reality is not 5 in size at all:

There are already `SetSizeWithCurrentAnchor` but how to get other's `RectTransform`'s absolute size?

# Answer
> 1 votes
RectTransform does not take any scaling (of itself or any parents) into account when performing layout or determining what the reported rect is. Try doing all UI layout with no scaling, setting only the RectTransform’s anchored position, size delta and anchors for position, and only relying on the CanvasScaler in the root Canvas to set the size on screen that you want.

If that doesn’t solve your problem, try starting from scratch and building just a visual copy without doing any scaling, and find the differences.

---
Tags: unity
---


title: Unet Syncing within AR Hololens

text:
# Question
Title: Unet Syncing within AR Hololens
I am out of options. I have tried everything I could and no matter what I do, the Transforms don't sync up. I have had multiple solutions that worked in my test, non AR project, but once I put on the HoloLens, it doesn't work. Here is what I did:

```
//PlayerObject that is spawned by the NetworkManager
//(obviously has Network Identity component)
public class ClientObject : NetworkBehaviour {
    public static ClientObject CurrentClient;

    private void Start() {
        if(isLocalClient) CurrentClient = this;
    }

    public void MoveObject(GameObject obj, Vector3 position) {
        Cmd_MoveObject(obj, position);
    }

    [Command]
    public void Cmd_MoveObject(GameObject obj, Vector3 position) {
        obj.transform.localPosition = position;
    }
}

```

And now the object that wants to get synced. It has a Network Transform with standard settings, a network identity and (obviously) no-one has authority since it doesn't get spawned:

```
public class AnObject : MonoBehaviour {
    public void IWasMoved() {
        /*
         * Someone Moved this object, either by dragging it or
         * clicking on one of it's arrows through the hololons.
         */

        Vector3 newPosition = (the new position i want this object to have);
        ClientObject.CurrentClient.MoveObject(gameObject, newPosition);
    }
}

```

That's what I have. The only thing different from the version that works on my PC without the HoloLens is that I don't set `localPosition = position`, but instead use `Translate(position)` (which is obviously the non local version);

I am tired of writing new code, building the project, having Visual Studio translate the code to C++, start my HoloLenses and test if it works, which takes over an hour every time I do so.

So: is there anything fundamentally wrong with my code? Again: it works on my test project just fine. I refuse to believe that it's the HoloLens's fault...

# Answer
> 0 votes
So as far as i'm aware this has no solution. Apparently the hololens is incompatable with syncing objects that weren't spawned in Unet. I took the long road and coded the entire backend of server and client communication since Unet is unable to handle it... A pity.

---
Tags: unity, c#, augmented-reality, unet, hololens
---


# Question
Title: What exactly does XMMatrixPerspective{L,R}H do?
There are generally three functions to create a perspective matrix in DirectXMath, `XMMatrixPerspective{L,R}H`, `XMMatrixPerspectiveFov{L,R}H` and `XMMatrixPerspectiveOffCenter{L,R}H`. I'm kind of confused what `XMMatrixPerspective` exactly does.

I'm currently generating a perspective matrix using

```
DirectX::XMMatrixPerspectiveFovRH(to_rad(80.0f), (float)winX / (float)winY, 0.1f, 100.0f);

```

which works fine, I can see the cube I'm drawing in front of me. If I replace this with a `DirectX::XMMatrixPerspectiveRH(winX, winY, 0.1f, 100.0f)`, I don't see anything on the screen. So the question is, *what exactly* does the matrix represent? What is it's field of view? And why don't I see my cube? If this function uses some sort of default fov value, I'd expect to see my cube - even if possibly stretched - as my view matrix looks straight at it.

Unfortunately, the docs only say "creates a projection matrix" but nothing about how one is supposed to work with that matrix.

E: I figured out, I'm not supposed to pass the window coordinates. It expects the size of the near-clipping plane. However after playing around for a bit with values, how is this function supposed to be used? I really can't see any reason to use this over the one where you pass in a fov.

# Answer
The DirectXMath library is all inline so you can look directly at the source.

For example, here is the C version of `XMMatrixPerspectiveLH`:

```
float TwoNearZ = NearZ + NearZ;
float fRange = FarZ / (FarZ - NearZ);

XMMATRIX M;
M.m[0][0] = TwoNearZ / ViewWidth;
M.m[0][1] = 0.0f;
M.m[0][2] = 0.0f;
M.m[0][3] = 0.0f;

M.m[1][0] = 0.0f;
M.m[1][1] = TwoNearZ / ViewHeight;
M.m[1][2] = 0.0f;
M.m[1][3] = 0.0f;

M.m[2][0] = 0.0f;
M.m[2][1] = 0.0f;
M.m[2][2] = fRange;
M.m[2][3] = 1.0f;

M.m[3][0] = 0.0f;
M.m[3][1] = 0.0f;
M.m[3][2] = -fRange * NearZ;
M.m[3][3] = 0.0f;
return M;

```

and here is the C version of `XMMatrixPerspectiveFovLH`:

```
float Height = CosFov / SinFov;
float Width = Height / AspectRatio;
float fRange = FarZ / (FarZ-NearZ);

XMMATRIX M;
M.m[0][0] = Width;
M.m[0][1] = 0.0f;
M.m[0][2] = 0.0f;
M.m[0][3] = 0.0f;

M.m[1][0] = 0.0f;
M.m[1][1] = Height;
M.m[1][2] = 0.0f;
M.m[1][3] = 0.0f;

M.m[2][0] = 0.0f;
M.m[2][1] = 0.0f;
M.m[2][2] = fRange;
M.m[2][3] = 1.0f;

M.m[3][0] = 0.0f;
M.m[3][1] = 0.0f;
M.m[3][2] = -fRange * NearZ;
M.m[3][3] = 0.0f;
return M;

```

The "FOV" version compute the size of the projection plane rectangle from the provided field-of-view and aspect ratio values, while the non-FOV version takes a project plane rectangle size directly. The FOV version is the one you most commonly use as it provides a 'physical camera like' control that's easier to understand.
> 2 votes

---
Tags: matrix, projection-matrix, directxmath
---