Transfer Functions (WIP - TODO: Make GUI)
This commit is contained in:
Родитель
2b5d44ccb8
Коммит
669634fd6f
|
@ -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:
|
Загрузка…
Ссылка в новой задаче