Skip to content

Commit

Permalink
Work on water sim
Browse files Browse the repository at this point in the history
Still trying to get the water sim to work. I might have an idea to make it work though.
  • Loading branch information
AIP21 committed Mar 30, 2023
1 parent f9af63d commit 41f3420
Show file tree
Hide file tree
Showing 374 changed files with 5,948 additions and 465,155 deletions.
193 changes: 114 additions & 79 deletions Assets/FluidSim/ComputerShaders/ComputeShaderTest.cs
Original file line number Diff line number Diff line change
@@ -1,122 +1,157 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ComputeShaderTest : MonoBehaviour
{
// Public
[Header("References")]
public ComputeShader computeShader;
public RenderTexture renderTexture;

private int[] cells;
public RenderTexture RT;
public RenderTexture newRT;
public RenderTexture outputRT;
public Texture2D heightmap;

[Header("Settings")]
public int resolution = 256;

public float diffusionFactor = 0.1f;
[Range(0, 25)]
public int brushSize = 8;
public Vector2 brushPosition = new Vector2(0, 0);
public bool drawing = false;

public int filledCount = 0;
public int filledAvg = 0;
public int maxValue = 10;

[Header("Water source")]
public float sourceRate = 1;
[Range(0, 25)]
public int sourceSize = 4;
public int sourceAmount = 1;
public Vector2Int sourcePosition;

// Private
private float lastSourceTime = 0;

private void Awake()
{
cells = new int[resolution * resolution];
for (int i = 0; i < resolution * resolution; i++)
sourcePosition = new Vector2Int(resolution / 2, resolution / 5);

if (outputRT == null)
{
outputRT = new RenderTexture(resolution, resolution, 24);
outputRT.enableRandomWrite = true;
outputRT.Create();
}
if (RT == null)
{
RT = new RenderTexture(resolution, resolution, 24);
RT.enableRandomWrite = true;
RT.Create();
}
if (newRT == null)
{
cells[i] = 0;
newRT = new RenderTexture(resolution, resolution, 24);
newRT.enableRandomWrite = true;
newRT.Create();
}
}

public void ComputeWater()
public void FixedUpdate()
{
int intSize = sizeof(int);
int totalSize = intSize;

ComputeBuffer cellsBuffer = new ComputeBuffer(cells.Length, totalSize);
cellsBuffer.SetData(cells);
if (outputRT == null)
{
outputRT = new RenderTexture(resolution, resolution, 24);
outputRT.enableRandomWrite = true;
outputRT.Create();
}
if (RT == null)
{
RT = new RenderTexture(resolution, resolution, 24);
RT.enableRandomWrite = true;
RT.Create();
}
if (newRT == null)
{
newRT = new RenderTexture(resolution, resolution, 24);
newRT.enableRandomWrite = true;
newRT.Create();
}

computeShader.SetBuffer(0, "cells", cellsBuffer);
computeShader.SetTexture(0, "output", renderTexture);
computeShader.SetInt("fillX", 0);
computeShader.SetInt("fillY", 0);
computeShader.SetInt("fillRadius", 0);
computeShader.SetInt("resolution", resolution);
computeShader.SetInt("brushSize", brushSize);
computeShader.SetInt("brushX", (int) brushPosition.x);
computeShader.SetInt("brushY", (int) brushPosition.y);
computeShader.SetInt("drawing", drawing ? 1 : 0);
computeShader.Dispatch(0, renderTexture.width / 8, renderTexture.height / 8, 1);
computeShader.SetInt("maxWater", maxValue);
computeShader.SetInt("filling", 0);
computeShader.SetFloat("diffusionFactor", diffusionFactor);
computeShader.SetTexture(0, "Output", outputRT);
computeShader.SetTexture(0, "Watermap", RT);
computeShader.SetTexture(0, "NewWatermap", newRT);
computeShader.SetTexture(0, "Heightmap", heightmap);

cellsBuffer.GetData(cells);
// Copy newRT to RT
Graphics.Blit(newRT, RT);

cellsBuffer.Dispose();

filledCount = 0;
int sum = 0;
for (int i = 0; i < cells.Length; i++)
// Add water at the mouse position when clicking
if (Input.GetMouseButton(0))
{
if (cells[i] > 0)
{
filledCount++;
sum += cells[i];
}
fillCircle((int)(Input.mousePosition.x / Screen.width * resolution), (int)(Input.mousePosition.y / Screen.height * resolution), brushSize);
}

filledAvg = sum / filledCount;
}

public void FixedUpdate()
{
// Add water at the mouse position when clicking
if (Input.GetMouseButton(0))
// Add water from source
if (sourceRate != 0 && lastSourceTime + sourceRate < Time.time)
{
drawing = true;
brushPosition = Input.mousePosition;
brushPosition.x = brushPosition.x / Screen.width * resolution;
brushPosition.y = brushPosition.y / Screen.height * resolution;
} else {
drawing = false;
fillCircle(sourcePosition.x, sourcePosition.y, sourceSize, sourceAmount);
lastSourceTime = Time.time;
}

computeShader.Dispatch(0, RT.width / 8, RT.height / 8, 1);
}

private void OnRenderImage(RenderTexture src, RenderTexture dest)
{
if (renderTexture == null)
if(outputRT == null)
{
outputRT = new RenderTexture(resolution, resolution, 24);
outputRT.enableRandomWrite = true;
outputRT.Create();
}
if (RT == null)
{
renderTexture = new RenderTexture(resolution, resolution, 24);
renderTexture.enableRandomWrite = true;
renderTexture.Create();
RT = new RenderTexture(resolution, resolution, 24);
RT.enableRandomWrite = true;
RT.Create();
}
if (newRT == null)
{
newRT = new RenderTexture(resolution, resolution, 24);
newRT.enableRandomWrite = true;
newRT.Create();
}

ComputeWater();
Graphics.Blit(outputRT, dest);
}

Graphics.Blit(renderTexture, dest);
private void fillCircle(int xCenter, int yCenter, int size, int amount = 10)
{
computeShader.SetInt("fillX", xCenter);
computeShader.SetInt("fillY", yCenter);
computeShader.SetInt("fillRadius", size);
computeShader.SetInt("filling", 1);
}

private void OnGUI()
public void OnGUI()
{
if (cells != null)
if (GUI.Button(new Rect(10, 10, 100, 30), "Clear"))
{
if (GUI.Button(new Rect(0, 60, 100, 50), "Clear"))
{
for (int i = 0; i < resolution * resolution; i++)
{
cells[i] = 0;
}
}

if (GUI.Button(new Rect(0, 120, 100, 50), "Add water"))
{
// Fill a circle in the center of the screen
for (int y = 0; y < resolution; y++)
{
for (int x = 0; x < resolution; x++)
{
int index = y * resolution + x;
if (Vector2.Distance(new Vector2(x, y), new Vector2(resolution / 2, resolution / 2)) < 10)
{
cells[index] = 10;
}
}
}
}
outputRT = new RenderTexture(resolution, resolution, 24);
outputRT.enableRandomWrite = true;
outputRT.Create();
RT = new RenderTexture(resolution, resolution, 24);
RT.enableRandomWrite = true;
RT.Create();
newRT = new RenderTexture(resolution, resolution, 24);
newRT.enableRandomWrite = true;
newRT.Create();
}
}
}
15 changes: 13 additions & 2 deletions Assets/FluidSim/ComputerShaders/ComputerShaderScene.unity
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.12731704, g: 0.13414727, b: 0.121078536, a: 1}
m_IndirectSpecularColor: {r: 0.12731749, g: 0.13414757, b: 0.1210787, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
Expand Down Expand Up @@ -221,4 +221,15 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
computeShader: {fileID: 7200000, guid: 2b89ddd0b7cf8c74d878e4d03c57b66d, type: 3}
renderTexture: {fileID: 0}
RT: {fileID: 0}
newRT: {fileID: 0}
outputRT: {fileID: 0}
heightmap: {fileID: 2800000, guid: 36341a9953beaf84eba6cf08cef3c594, type: 3}
resolution: 128
diffusionFactor: 0.1
brushSize: 8
maxValue: 10
sourceRate: 0
sourceSize: 8
sourceAmount: 1
sourcePosition: {x: 0, y: 0}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#pragma kernel CSMain

RWTexture2D<float4> Result;
int _Size;
float _Time;
float2 _MousePos;
int _MouseMode;
//=========================================================================
float4 GetResultPixel(int2 pID_new)
{
float4 result = Result[pID_new];
//if( pID_new.x < 0 || pID_new.x >= _Size || pID_new.y < 0 || pID_new.y >= _Size ) result = float4(0,1,1,1); //outside canvas is obstacle
return result;
}

void MakeNewPixelObstacle(int2 id)
{
float4 p = Result[id];
if( _MouseMode == 0 && p.x == 0 && p.z == 0 ) Result[id] = float4(1,1,0,1);
else if( _MouseMode == 1 ) Result[id] = float4(0,1,1,1);
else if( _MouseMode == 2 && p.x == 0 ) Result[id] = float4(0,0,0,1);
}

float random(float2 st)
{
return frac(sin(dot(st.xy,float2(12.9898f, 78.233f)))*43758.5453123f);
}
//============================= MAIN ====================================
[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
//make new pixel / obstacle ----------------------
int2 newPixelID = _MousePos*_Size;
if( _MouseMode != 0)
{
//so that the brush is thicker
float dist = distance(float2(id.xy),float2(newPixelID));
if(dist < 2.5f) MakeNewPixelObstacle(id.xy);
}
else
{
MakeNewPixelObstacle(newPixelID);
}

//move pixels ----------------------
int2 pID = id.xy;
float4 p = Result[pID];

if(p.x == 1)
{
//move down
int2 direction = int2( 0 , -1 );
int2 pID_new = pID+direction;//*(10*p.y);
float4 p_new = GetResultPixel(pID_new);

//if not empty - move horizontal
if(p_new.x > 0 || p_new.z > 0)
{
direction = int2( sign(random(float2(pID) + _Time)-0.5f) , -1 );
pID_new = pID+direction;
p_new = GetResultPixel(pID_new);
}

//if empty - assign
if(p_new.x == 0 && p_new.z == 0)
{
Result[pID_new] = p;
Result[pID] = float4(0,0,0,1);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 41f3420

Please sign in to comment.