Transfer Functions (WIP - TODO: Make GUI)

This commit is contained in:
Matias 2019-02-12 14:04:11 +01:00
Родитель 2b5d44ccb8
Коммит 669634fd6f
11 изменённых файлов: 191 добавлений и 26 удалений

8
Assets/Editor.meta Normal file
Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ffef5df4aac96a943aee0f9f9b923559
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,6 @@
using UnityEngine;
using UnityEditor;
public class TransferFunctionEditorWindow : EditorWindow
{
}

Просмотреть файл

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6bea1cf561897604ea2e430d753f593e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -328,10 +328,10 @@ Transform:
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 326583332}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalRotation: {x: 0, y: -0.7071068, z: -0.7071068, w: 0}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_LocalEulerAnglesHint: {x: 270, y: 0, z: 180}

Просмотреть файл

@ -47,28 +47,20 @@ public class VolumeRenderer : MonoBehaviour
noiseCols[iX + iY * noiseDimX] = new Color(pixVal, pixVal, pixVal);
}
}
TransferFunction tf = new TransferFunction();
tf.AddControlPoint(new TFColourControlPoint(0.0f, Color.black));
tf.AddControlPoint(new TFColourControlPoint(0.055f, Color.yellow));
tf.AddControlPoint(new TFColourControlPoint(0.11f, Color.red));
tf.AddControlPoint(new TFColourControlPoint(1.0f, Color.white));
const int tfDimX = 1024;
const int tfDimY = 1024;
tf.AddControlPoint(new TFAlphaControlPoint(0.0f, 0.0f));
tf.AddControlPoint(new TFAlphaControlPoint(0.01f, 0.0f));
tf.AddControlPoint(new TFAlphaControlPoint(0.6f, 0.2f));
tf.AddControlPoint(new TFAlphaControlPoint(1.0f, 1.0f));
Texture2D tfTexture = new Texture2D(tfDimX, tfDimY, TextureFormat.RGBAFloat, false);
Color[] tfCols = new Color[tfDimX * tfDimY];
for (int iX = 0; iX < tfDimX; iX++)
{
float t = (float)iX / tfDimX;
Color col = t > 0.28f ? Color.white : (t > 0.026f && t < 0.103f ? Color.green : Color.red);
float alpha = Mathf.Lerp(0.0f, 1.0f, t > 0.01f ? t : 0.0f);
Color tfVal = new Color(col.r, col.g, col.b, alpha);
for (int iY = 0; iY < tfDimY; iY++)
{
tfCols[iX + iY * tfDimX] = tfVal;
}
}
Texture2D tfTexture = tf.GetTexture();
// Copy the pixel data to the texture and load it into the GPU.
tfTexture.wrapMode = TextureWrapMode.Clamp;
tfTexture.SetPixels(tfCols);
tfTexture.Apply();
GetComponent<MeshRenderer>().sharedMaterial.SetTexture("_DataTex", tex);
GetComponent<MeshRenderer>().sharedMaterial.SetTexture("_NoiseTex", noiseTexture);

Просмотреть файл

@ -23,7 +23,7 @@
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
@ -61,7 +61,7 @@
fixed4 frag (v2f i) : SV_Target
{
#define NUM_STEPS 40//200
#define NUM_STEPS 500//200
const float stepSize = 1.732f/*greatest distance in box*/ / NUM_STEPS;
float4 col = float4(i.vertexLocal.x, i.vertexLocal.y, i.vertexLocal.z, 1.0f);
@ -75,7 +75,7 @@
col = float4(0.0f, 0.0f, 0.0f, 0.0f);
float maxDensity = 0.0f;
[unroll]
//[unroll(NUM_STEPS)]
for (uint iStep = 0; iStep < NUM_STEPS; iStep++)
{
const float t = iStep * stepSize + stepSize * 0.5f;
@ -83,9 +83,10 @@
if (currPos.x < 0.0f || currPos.x >= 1.0f || currPos.y < 0.0f || currPos.y > 1.0f || currPos.z < 0.0f || currPos.z > 1.0f) // TODO: avoid branch?
break;
float density = tex3D(_DataTex, currPos).r / 4095.0f;
//const float density = tex3D(_DataTex, currPos).r / 4095.0f;
const float density = tex3Dlod(_DataTex, float4(currPos.x, currPos.y, currPos.z, 0.0f)).r / 4095.0f;
float4 src = tex2D(_TFTex, float2(density, 0.0f));
float4 src = tex2Dlod(_TFTex, float4(density, 0.0f, 0.0f, 0.0f));// tex2D(_TFTex, float2(density, 0.0f));
if (density < _MinVal || density > _MaxVal)
src.a = 0.0f;

Просмотреть файл

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 27b7f465119ea6944a0ecf0436c4f2ee
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,25 @@
using UnityEngine;
public struct TFColourControlPoint
{
public float dataValue;
public Color colourValue;
public TFColourControlPoint(float dataValue, Color colourValue)
{
this.dataValue = dataValue;
this.colourValue = colourValue;
}
}
public struct TFAlphaControlPoint
{
public float dataValue;
public float alphaValue;
public TFAlphaControlPoint(float dataValue, float alphaValue)
{
this.dataValue = dataValue;
this.alphaValue = alphaValue;
}
}

Просмотреть файл

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ad1f61bc396155b4ea8f39b0f437ce24
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Просмотреть файл

@ -0,0 +1,92 @@
using UnityEngine;
using System.Collections.Generic;
public class TransferFunction
{
private List<TFColourControlPoint> colourControlPoints = new List<TFColourControlPoint>();
private List<TFAlphaControlPoint> alphaControlPoints = new List<TFAlphaControlPoint>();
private Texture2D texture = null;
private const int TEXTURE_WIDTH = 1024;
private const int TEXTURE_HEIGHT = 1024;
public void AddControlPoint(TFColourControlPoint ctrlPoint)
{
colourControlPoints.Add(ctrlPoint);
}
public void AddControlPoint(TFAlphaControlPoint ctrlPoint)
{
alphaControlPoints.Add(ctrlPoint);
}
public Texture2D GetTexture()
{
if (texture == null)
GenerateTexture();
return texture;
}
public void GenerateTexture()
{
texture = new Texture2D(TEXTURE_WIDTH, TEXTURE_HEIGHT, TextureFormat.RGBAFloat, false);
Color[] tfCols = new Color[TEXTURE_WIDTH * TEXTURE_HEIGHT];
List<TFColourControlPoint> cols = colourControlPoints;
List<TFAlphaControlPoint> alphas = alphaControlPoints;
// Sort lists of control points
cols.Sort((a, b) => (a.dataValue.CompareTo(b.dataValue)));
alphas.Sort((a, b) => (a.dataValue.CompareTo(b.dataValue)));
// Add colour points at beginning and end
if (cols.Count == 0 || cols[cols.Count - 1].dataValue < 1.0f)
cols.Add(new TFColourControlPoint(1.0f, Color.white));
if(cols[0].dataValue > 0.0f)
cols.Insert(0, new TFColourControlPoint(0.0f, Color.white));
// Add alpha points at beginning and end
if (alphas.Count == 0 || alphas[alphas.Count - 1].dataValue < 1.0f)
alphas.Add(new TFAlphaControlPoint(1.0f, 1.0f));
if (alphas[0].dataValue > 0.0f)
alphas.Insert(0, new TFAlphaControlPoint(0.0f, 0.0f));
int numColours = cols.Count;
int numAlphas = alphas.Count;
int iCurrColour = 0;
int iCurrAlpha = 0;
for(int iX = 0; iX < TEXTURE_WIDTH; iX++)
{
float t = iX / (float)(TEXTURE_WIDTH - 1);
while (iCurrColour < numColours - 2 && cols[iCurrColour + 1].dataValue < t)
iCurrColour++;
while (iCurrAlpha < numAlphas - 2 && alphas[iCurrAlpha + 1].dataValue < t)
iCurrAlpha++;
TFColourControlPoint leftCol = cols[iCurrColour];
TFColourControlPoint rightCol = cols[iCurrColour + 1];
TFAlphaControlPoint leftAlpha = alphas[iCurrAlpha];
TFAlphaControlPoint rightAlpha = alphas[iCurrAlpha + 1];
float tCol = (Mathf.Clamp(t, leftCol.dataValue, rightCol.dataValue) - leftCol.dataValue) / (rightCol.dataValue - leftCol.dataValue);
float tAlpha = (Mathf.Clamp(t, leftAlpha.dataValue, rightAlpha.dataValue) - leftAlpha.dataValue) / (rightAlpha.dataValue - leftAlpha.dataValue);
Color pixCol = rightCol.colourValue * tCol + leftCol.colourValue * (1.0f - tCol);
pixCol.a = rightAlpha.alphaValue * tAlpha + leftAlpha.alphaValue * (1.0f - tAlpha);
for (int iY = 0; iY < TEXTURE_HEIGHT; iY++)
{
tfCols[iX + iY * TEXTURE_WIDTH] = pixCol;
}
}
texture.wrapMode = TextureWrapMode.Clamp;
texture.SetPixels(tfCols);
texture.Apply();
}
}

Просмотреть файл

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 33f90861ddebbc14486139d1bbdf1c77
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: