Skip to content

Commit e384230

Browse files
committed
Added double buffer
1 parent 4ebb6bc commit e384230

14 files changed

+827
-3
lines changed

Assets/Patterns/19. Spatial Partition/Grid/Ground.mat renamed to Assets/Patterns/19. Spatial Partition/Grid/Ground mat.mat

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Material:
77
m_CorrespondingSourceObject: {fileID: 0}
88
m_PrefabInstance: {fileID: 0}
99
m_PrefabAsset: {fileID: 0}
10-
m_Name: Ground
10+
m_Name: Ground mat
1111
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
1212
m_ShaderKeywords:
1313
m_LightmapFlags: 4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
%YAML 1.1
2+
%TAG !u! tag:unity3d.com,2011:
3+
--- !u!21 &2100000
4+
Material:
5+
serializedVersion: 6
6+
m_ObjectHideFlags: 0
7+
m_CorrespondingSourceObject: {fileID: 0}
8+
m_PrefabInstance: {fileID: 0}
9+
m_PrefabAsset: {fileID: 0}
10+
m_Name: Unit mat
11+
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
12+
m_ShaderKeywords:
13+
m_LightmapFlags: 4
14+
m_EnableInstancingVariants: 0
15+
m_DoubleSidedGI: 0
16+
m_CustomRenderQueue: -1
17+
stringTagMap: {}
18+
disabledShaderPasses: []
19+
m_SavedProperties:
20+
serializedVersion: 3
21+
m_TexEnvs:
22+
- _BumpMap:
23+
m_Texture: {fileID: 0}
24+
m_Scale: {x: 1, y: 1}
25+
m_Offset: {x: 0, y: 0}
26+
- _DetailAlbedoMap:
27+
m_Texture: {fileID: 0}
28+
m_Scale: {x: 1, y: 1}
29+
m_Offset: {x: 0, y: 0}
30+
- _DetailMask:
31+
m_Texture: {fileID: 0}
32+
m_Scale: {x: 1, y: 1}
33+
m_Offset: {x: 0, y: 0}
34+
- _DetailNormalMap:
35+
m_Texture: {fileID: 0}
36+
m_Scale: {x: 1, y: 1}
37+
m_Offset: {x: 0, y: 0}
38+
- _EmissionMap:
39+
m_Texture: {fileID: 0}
40+
m_Scale: {x: 1, y: 1}
41+
m_Offset: {x: 0, y: 0}
42+
- _MainTex:
43+
m_Texture: {fileID: 0}
44+
m_Scale: {x: 1, y: 1}
45+
m_Offset: {x: 0, y: 0}
46+
- _MetallicGlossMap:
47+
m_Texture: {fileID: 0}
48+
m_Scale: {x: 1, y: 1}
49+
m_Offset: {x: 0, y: 0}
50+
- _OcclusionMap:
51+
m_Texture: {fileID: 0}
52+
m_Scale: {x: 1, y: 1}
53+
m_Offset: {x: 0, y: 0}
54+
- _ParallaxMap:
55+
m_Texture: {fileID: 0}
56+
m_Scale: {x: 1, y: 1}
57+
m_Offset: {x: 0, y: 0}
58+
m_Floats:
59+
- _BumpScale: 1
60+
- _Cutoff: 0.5
61+
- _DetailNormalMapScale: 1
62+
- _DstBlend: 0
63+
- _GlossMapScale: 1
64+
- _Glossiness: 0.5
65+
- _GlossyReflections: 1
66+
- _Metallic: 0
67+
- _Mode: 0
68+
- _OcclusionStrength: 1
69+
- _Parallax: 0.02
70+
- _SmoothnessTextureChannel: 0
71+
- _SpecularHighlights: 1
72+
- _SrcBlend: 1
73+
- _UVSec: 0
74+
- _ZWrite: 1
75+
m_Colors:
76+
- _Color: {r: 1, g: 1, b: 1, a: 1}
77+
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}

Assets/Patterns/19. Spatial Partition/Grid/Unit mat.mat.meta

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Patterns/19. Spatial Partition/Grid/Unit.prefab

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ MeshRenderer:
103103
m_RenderingLayerMask: 1
104104
m_RendererPriority: 0
105105
m_Materials:
106-
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
106+
- {fileID: 2100000, guid: f7606b68f74620c47be39f69a8a05821, type: 2}
107107
m_StaticBatchInfo:
108108
firstSubMesh: 0
109109
subMeshCount: 0

Assets/Patterns/7. Double Buffer.meta

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Patterns/7. Double Buffer/Cave.meta

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
%YAML 1.1
2+
%TAG !u! tag:unity3d.com,2011:
3+
--- !u!21 &2100000
4+
Material:
5+
serializedVersion: 6
6+
m_ObjectHideFlags: 0
7+
m_CorrespondingSourceObject: {fileID: 0}
8+
m_PrefabInstance: {fileID: 0}
9+
m_PrefabAsset: {fileID: 0}
10+
m_Name: Cave mat
11+
m_Shader: {fileID: 10752, guid: 0000000000000000f000000000000000, type: 0}
12+
m_ShaderKeywords:
13+
m_LightmapFlags: 4
14+
m_EnableInstancingVariants: 0
15+
m_DoubleSidedGI: 0
16+
m_CustomRenderQueue: -1
17+
stringTagMap: {}
18+
disabledShaderPasses: []
19+
m_SavedProperties:
20+
serializedVersion: 3
21+
m_TexEnvs:
22+
- _BumpMap:
23+
m_Texture: {fileID: 0}
24+
m_Scale: {x: 1, y: 1}
25+
m_Offset: {x: 0, y: 0}
26+
- _DetailAlbedoMap:
27+
m_Texture: {fileID: 0}
28+
m_Scale: {x: 1, y: 1}
29+
m_Offset: {x: 0, y: 0}
30+
- _DetailMask:
31+
m_Texture: {fileID: 0}
32+
m_Scale: {x: 1, y: 1}
33+
m_Offset: {x: 0, y: 0}
34+
- _DetailNormalMap:
35+
m_Texture: {fileID: 0}
36+
m_Scale: {x: 1, y: 1}
37+
m_Offset: {x: 0, y: 0}
38+
- _EmissionMap:
39+
m_Texture: {fileID: 0}
40+
m_Scale: {x: 1, y: 1}
41+
m_Offset: {x: 0, y: 0}
42+
- _MainTex:
43+
m_Texture: {fileID: 0}
44+
m_Scale: {x: 1, y: 1}
45+
m_Offset: {x: 0, y: 0}
46+
- _MetallicGlossMap:
47+
m_Texture: {fileID: 0}
48+
m_Scale: {x: 1, y: 1}
49+
m_Offset: {x: 0, y: 0}
50+
- _OcclusionMap:
51+
m_Texture: {fileID: 0}
52+
m_Scale: {x: 1, y: 1}
53+
m_Offset: {x: 0, y: 0}
54+
- _ParallaxMap:
55+
m_Texture: {fileID: 0}
56+
m_Scale: {x: 1, y: 1}
57+
m_Offset: {x: 0, y: 0}
58+
m_Floats:
59+
- _BumpScale: 1
60+
- _Cutoff: 0.5
61+
- _DetailNormalMapScale: 1
62+
- _DstBlend: 0
63+
- _GlossMapScale: 1
64+
- _Glossiness: 0.5
65+
- _GlossyReflections: 1
66+
- _Metallic: 0
67+
- _Mode: 0
68+
- _OcclusionStrength: 1
69+
- _Parallax: 0.02
70+
- _SmoothnessTextureChannel: 0
71+
- _SpecularHighlights: 1
72+
- _SrcBlend: 1
73+
- _UVSec: 0
74+
- _ZWrite: 1
75+
m_Colors:
76+
- _Color: {r: 1, g: 1, b: 1, a: 1}
77+
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}

Assets/Patterns/7. Double Buffer/Cave/Cave mat.mat.meta

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
using UnityEngine;
4+
5+
namespace DoubleBuffer.Cave
6+
{
7+
//Illustrate the Double Buffer game programming pattern by generating a cave pattern and display it on a plane
8+
//The idea is based on this Unity tutorial https://www.youtube.com/watch?v=v7yyZZjF1z4
9+
public class GameController : MonoBehaviour
10+
{
11+
//Display the pattern on this plane
12+
public MeshRenderer displayPlaneRenderer;
13+
14+
//Is used to init the cellular automata by spreading random dots on a grid
15+
//And from these dots we will generate caves
16+
//The higher the fill percentage, the smaller the caves
17+
[Range(0, 1)]
18+
public float randomFillPercent;
19+
20+
//The double buffer
21+
//Notice that the Unity tutorial is using one buffer, which works but is not entirely correct because it results in a strong diagonal bias
22+
//Someone in the comment section is also complaining about it, so this is the correct version
23+
//Is storing int where 1 is wall and 0 is cave
24+
private int[,] bufferOld;
25+
private int[,] bufferNew;
26+
27+
//The size of the grid
28+
private const int GRID_SIZE = 100;
29+
30+
//How many steps do we want to simulate?
31+
private const int SIMULATION_STEPS = 20;
32+
33+
//For how long will we pause between each simulation step so we can look at the result
34+
private float PAUSE_TIME = 1f;
35+
36+
37+
38+
void Start()
39+
{
40+
bufferOld = new int[GRID_SIZE, GRID_SIZE];
41+
bufferNew = new int[GRID_SIZE, GRID_SIZE];
42+
43+
//Init the old values so we can calculate the new values
44+
for (int x = 0; x < GRID_SIZE; x++)
45+
{
46+
for (int y = 0; y < GRID_SIZE; y++)
47+
{
48+
//We dont want holes in our walls, so the border is always a wall
49+
if (x == 0 || x == GRID_SIZE - 1 || y == 0 || y == GRID_SIZE - 1)
50+
{
51+
bufferOld[x, y] = 1;
52+
}
53+
//Random walls and caves
54+
else
55+
{
56+
bufferOld[x, y] = Random.Range(0f, 1f) < randomFillPercent ? 1 : 0;
57+
}
58+
}
59+
}
60+
61+
//For testing that init is working
62+
//GenerateAndDisplayTexture(bufferOld);
63+
64+
//Start the simulation
65+
StartCoroutine(SimulateCavePattern());
66+
}
67+
68+
69+
70+
//Do the simulation in a coroutine so we can pause and see what's going on
71+
private IEnumerator SimulateCavePattern()
72+
{
73+
for (int i = 0; i < SIMULATION_STEPS; i++)
74+
{
75+
//Calculate the new values
76+
RunCellularAutomataStep();
77+
78+
//Generate texture and display it on the plane
79+
GenerateAndDisplayTexture(bufferNew);
80+
81+
//Swap the pointers to the buffers
82+
int[,] temp = bufferOld;
83+
84+
bufferOld = bufferNew;
85+
86+
bufferNew = temp;
87+
88+
yield return new WaitForSeconds(PAUSE_TIME);
89+
}
90+
}
91+
92+
93+
94+
//Generate caves by smoothing the data
95+
//Remember to always put the new results in bufferNew and use bufferOld to do the calculations
96+
private void RunCellularAutomataStep()
97+
{
98+
for (int x = 0; x < GRID_SIZE; x++)
99+
{
100+
for (int y = 0; y < GRID_SIZE; y++)
101+
{
102+
//Border is always wall
103+
if (x == 0 || x == GRID_SIZE - 1 || y == 0 || y == GRID_SIZE - 1)
104+
{
105+
bufferNew[x, y] = 1;
106+
107+
continue;
108+
}
109+
110+
//Uses bufferOld to get the wall count
111+
int surroundingWalls = GetSurroundingWallCount(x, y);
112+
113+
//Use some smoothing rules to generate caves
114+
if (surroundingWalls > 4)
115+
{
116+
bufferNew[x, y] = 1;
117+
}
118+
else if (surroundingWalls == 4)
119+
{
120+
bufferNew[x, y] = bufferOld[x, y];
121+
}
122+
else
123+
{
124+
bufferNew[x, y] = 0;
125+
}
126+
}
127+
}
128+
}
129+
130+
131+
132+
//Given a cell, how many of the 8 surrounding cells are walls?
133+
private int GetSurroundingWallCount(int cellX, int cellY)
134+
{
135+
int wallCounter = 0;
136+
137+
for (int neighborX = cellX - 1; neighborX <= cellX + 1; neighborX ++)
138+
{
139+
for (int neighborY = cellY - 1; neighborY <= cellY + 1; neighborY++)
140+
{
141+
//We dont need to care about being outside of the grid because we are never looking at the border
142+
143+
//This is the cell itself and no neighbor!
144+
if (neighborX == cellX && neighborY == cellY)
145+
{
146+
continue;
147+
}
148+
149+
//This neighbor is a wall
150+
if (bufferOld[neighborX, neighborY] == 1)
151+
{
152+
wallCounter += 1;
153+
}
154+
}
155+
}
156+
157+
return wallCounter;
158+
}
159+
160+
161+
162+
//Generate a black or white texture depending on if the pixel is cave or wall
163+
//Display the texture on a plane
164+
private void GenerateAndDisplayTexture(int[,] data)
165+
{
166+
//These two arrays are always the same so we could init them once at start
167+
Texture2D texture = new Texture2D(GRID_SIZE, GRID_SIZE);
168+
169+
texture.filterMode = FilterMode.Point;
170+
171+
Color[] textureColors = new Color[GRID_SIZE * GRID_SIZE];
172+
173+
for (int y = 0; y < GRID_SIZE; y++)
174+
{
175+
for (int x = 0; x < GRID_SIZE; x++)
176+
{
177+
//From 2d array to 1d array
178+
textureColors[y * GRID_SIZE + x] = data[x, y] == 1 ? Color.black : Color.white;
179+
}
180+
}
181+
182+
texture.SetPixels(textureColors);
183+
184+
texture.Apply();
185+
186+
displayPlaneRenderer.sharedMaterial.mainTexture = texture;
187+
}
188+
}
189+
}

0 commit comments

Comments
 (0)