summaryrefslogtreecommitdiffstats
path: root/math.cginc
blob: 02d0fe0e60dc7128db79db8c2f8d3316e4bae7d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#ifndef __MATH_INC
#define __MATH_INC

#define PI              3.14159265358979323846264f
#define TAU             (2.0f * PI)
#define HALF_PI         (PI * 0.5f)
#define RCP_PI          (1.0f / PI)
#define RCP_TAU         (1.0f / TAU)
#define PHI             1.618033989f
#define RCP_PHI         0.618033989f
#define SQRT_2          1.414213562f
#define SQRT_2_RCP      0.707106781f
#define RCP_SQRT_2      0.707106781f
#define RCP_SQRT_3      0.577350269f
#define TWO_OVER_THREE  0.6666666666666666f
#define SQRT_3          1.73205081f
#define SQRT_3_OVER_2   0.8660254037844386f
#define EULERS_CONSTANT 2.718281828f

float sin_noise_3d(float3 uvw) {
  return sin(uvw[0]) * sin(uvw[1]) * sin(uvw[2]);
}

float sin_noise_3d_fbm(float3 uvw, uint octaves, float k, float strength) {
  float result = 0;
  float factor = 1.0f;
  for (uint i = 0; i < octaves; i++) {
    result += sin_noise_3d(uvw) * factor * strength;
    uvw *= k;
    factor /= k;
  }
  return result;
}

// Wrap a dot product. Assume it's already clamped.
// At k=0, you get standard lambertian shading.
// At k=0.5, you get half-lambertian shading.
// At k=1.0, you get flat shading.
// k must be on [0, 1].
// Energy preserving, within some small bound.
float wrapDotProduct(float XoY, float k) {
  float lambertian = XoY;
  float half_lambertian = pow(max(1e-4, (XoY + 0.5f) / (1.0f + 0.5f)), 2);
  float flat = RCP_PI;

  if (k < 0.5) {
    return lerp(lambertian, half_lambertian, k * 2.0f);
  } else {
    return lerp(half_lambertian, flat, k * 2.0f - 1.0f);
  }
}

// Vector rotation with a quaternion
// https://blog.molecular-matters.com/2013/05/24/a-faster-quaternion-vector-multiplication/
float3 rotate_vector(float3 v, float4 q)
{
  float3 t = 2.0 * cross(q.xyz, v);
  return v + q.w * t + cross(q.xyz, t);
}

// Cartesian to cube hexagonal coordinates.
// Based on this: https://backdrifting.net/post/064_hex_grids
float3 cart_to_hex(float2 cart) {
  float p = cart.x;
  float q = dot(cart, float2(0.5f, SQRT_3_OVER_2));
  float r = dot(cart, float2(0.5f, -SQRT_3_OVER_2));

  return float3(p, q, r) * 0.5f;
}

float2 hex_to_cart(float3 cart) {
  return float2(
      cart[0] + (cart[1] + cart[2]) * 0.5f,
      (cart[1] - cart[2]) * SQRT_3_OVER_2);
}


float3 round_hex(float3 hex_coord) {
    float3 rounded = round(hex_coord);
    float3 diff = abs(rounded - hex_coord);
    float error = rounded.x - rounded.y - rounded.z;

    float3 max_mask = float3(
        diff.x > diff.y && diff.x > diff.z,
        diff.y > diff.x && diff.y > diff.z,
        diff.z > diff.x && diff.z > diff.y);

    rounded += error * float3(-1, 1, 1) * max_mask;
    return rounded;
}

// Reoriented normal mapping
// https://blog.selfshadow.com/publications/blending-in-detail/
// Inputs are in tangent space.
float3 blendNormalsHill12(float3 n0, float3 n1) {
  n0.z += 1.0;
  n1.xy = -n1.xy;
  
  return normalize(n0 * dot(n0, n1) - n1 * n0.z);
}

#endif  // __MATH_INC