| 1 | // Ogre port of Nvidia's IsoSurf.cg file |
|---|
| 2 | // Modified code follows. See http://developer.download.nvidia.com/SDK/10/opengl/samples.html for original |
|---|
| 3 | // |
|---|
| 4 | // Cg port of Yury Uralsky's metaball FX shader |
|---|
| 5 | // |
|---|
| 6 | // Authors: Simon Green and Yury Urlasky |
|---|
| 7 | // Email: sdkfeedback@nvidia.com |
|---|
| 8 | // |
|---|
| 9 | // Copyright (c) NVIDIA Corporation. All rights reserved. |
|---|
| 10 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 11 | |
|---|
| 12 | struct SampleData |
|---|
| 13 | { |
|---|
| 14 | float4 Pos : POSITION; |
|---|
| 15 | float3 N : TEXCOORD0; |
|---|
| 16 | float2 Field : TEXCOORD1; |
|---|
| 17 | float4 Color : COLOR0; |
|---|
| 18 | }; |
|---|
| 19 | |
|---|
| 20 | struct SurfaceVertex |
|---|
| 21 | { |
|---|
| 22 | float4 Pos : POSITION; |
|---|
| 23 | float3 N : TEXCOORD0; |
|---|
| 24 | }; |
|---|
| 25 | |
|---|
| 26 | uniform int Num_Metaballs = 2; |
|---|
| 27 | uniform float4 Metaballs[] = { |
|---|
| 28 | { -0.5, 0, 0, 0.2 }, |
|---|
| 29 | { 0.6, 0, 0, 0.4 }, |
|---|
| 30 | }; |
|---|
| 31 | |
|---|
| 32 | // Size of the sampling grid |
|---|
| 33 | uniform int3 SizeMask = { 63, 63, 63 }; |
|---|
| 34 | uniform int3 SizeShift = { 0, 6, 12 }; |
|---|
| 35 | |
|---|
| 36 | uniform float IsoValue = 1.0; |
|---|
| 37 | |
|---|
| 38 | // Metaball function |
|---|
| 39 | // Returns metaball function value in .w and its gradient in .xyz |
|---|
| 40 | |
|---|
| 41 | float4 Metaball(float3 Pos, float3 Center, float RadiusSq) |
|---|
| 42 | { |
|---|
| 43 | float epsilon = 0.001; |
|---|
| 44 | |
|---|
| 45 | float3 Dist = Pos - Center; |
|---|
| 46 | float InvDistSq = 1 / (dot(Dist, Dist) + epsilon); |
|---|
| 47 | |
|---|
| 48 | float4 o; |
|---|
| 49 | o.xyz = -2 * RadiusSq * InvDistSq * InvDistSq * Dist; |
|---|
| 50 | o.w = RadiusSq * InvDistSq; |
|---|
| 51 | return o; |
|---|
| 52 | } |
|---|
| 53 | |
|---|
| 54 | // Vertex shader |
|---|
| 55 | SampleData mainVS(float4 pos : POSITION, |
|---|
| 56 | uniform float4x4 WorldViewProj, |
|---|
| 57 | uniform float4x4 origWorldViewIT) |
|---|
| 58 | { |
|---|
| 59 | SampleData o; |
|---|
| 60 | |
|---|
| 61 | // Sum up contributions from all metaballs |
|---|
| 62 | float4 Field = 0; |
|---|
| 63 | for (int i = 0; i<2; i++) |
|---|
| 64 | { |
|---|
| 65 | Field += Metaball(pos.xyz, Metaballs[i].xyz, Metaballs[i].w); |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | float3x3 WorldViewIT = { origWorldViewIT[0].xyz, origWorldViewIT[1].xyz, origWorldViewIT[2].xyz }; |
|---|
| 69 | |
|---|
| 70 | // Transform position and normals |
|---|
| 71 | o.Pos = mul(WorldViewProj, pos); |
|---|
| 72 | o.N = mul(WorldViewIT, Field.xyz); // we want normals in world space |
|---|
| 73 | o.Field.x = Field.w; |
|---|
| 74 | |
|---|
| 75 | // Generate in-out flags |
|---|
| 76 | o.Field.y = (Field.w < IsoValue) ? 1 : 0; |
|---|
| 77 | |
|---|
| 78 | o.Color = (Field*0.5+0.5) * (Field.w / 10.0); |
|---|
| 79 | return o; |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | |
|---|
| 83 | |
|---|
| 84 | // Estimate where isosurface intersects grid edge with endpoints v0, v1 |
|---|
| 85 | void CalcIntersection(float4 Pos0, |
|---|
| 86 | float3 N0, |
|---|
| 87 | float2 Field0, |
|---|
| 88 | float4 Pos1, |
|---|
| 89 | float3 N1, |
|---|
| 90 | float2 Field1) |
|---|
| 91 | { |
|---|
| 92 | float t = (IsoValue - Field0.x) / (Field1.x - Field0.x); |
|---|
| 93 | if ((Field0.x < IsoValue) && (Field1.x > Field0.x)) |
|---|
| 94 | { |
|---|
| 95 | if (t > 0 && t < 1) |
|---|
| 96 | { |
|---|
| 97 | float4 Pos = lerp(Pos0, Pos1, t); |
|---|
| 98 | float3 N = lerp(N0, N1, t); |
|---|
| 99 | emitVertex(Pos : POSITION, N : TEXCOORD0); |
|---|
| 100 | } |
|---|
| 101 | } |
|---|
| 102 | } |
|---|
| 103 | |
|---|
| 104 | // Geometry shader |
|---|
| 105 | // input: line with adjacency (tetrahedron) |
|---|
| 106 | // outputs: zero, one or two triangles depending if isosurface intersects tetrahedron |
|---|
| 107 | LINE_ADJ |
|---|
| 108 | TRIANGLE_OUT |
|---|
| 109 | void mainGS( |
|---|
| 110 | AttribArray<float4> Pos : POSITION, |
|---|
| 111 | AttribArray<float3> N : TEXCOORD0, |
|---|
| 112 | AttribArray<float2> Field : TEXCOORD1 |
|---|
| 113 | ) |
|---|
| 114 | { |
|---|
| 115 | // construct index for this tetrahedron |
|---|
| 116 | unsigned int index = (int(Field[0].y) << 3) | |
|---|
| 117 | (int(Field[1].y) << 2) | |
|---|
| 118 | (int(Field[2].y) << 1) | |
|---|
| 119 | int(Field[3].y); |
|---|
| 120 | |
|---|
| 121 | // don't bother if all vertices out or all vertices inside isosurface |
|---|
| 122 | if (index > 0 && index < 15) |
|---|
| 123 | { |
|---|
| 124 | //Uber-compressed version of the edge table. |
|---|
| 125 | unsigned int edgeListHex[] = |
|---|
| 126 | {0x0001cde0, 0x98b08c9d, 0x674046ce, 0x487bc480, |
|---|
| 127 | 0x21301d2e, 0x139bd910, 0x26376e20, 0x3b700000}; |
|---|
| 128 | |
|---|
| 129 | unsigned int edgeValFull = edgeListHex[index/2]; |
|---|
| 130 | unsigned int edgeVal = (index % 2 == 1) ? (edgeValFull & 0xFFFF) : ((edgeValFull >> 16) & 0xFFFF); |
|---|
| 131 | int4 e0 = int4((edgeVal >> 14) & 0x3, (edgeVal >> 12) & 0x3, (edgeVal >> 10) & 0x3, (edgeVal >> 8) & 0x3); |
|---|
| 132 | int4 e1 = int4((edgeVal >> 6) & 0x3, (edgeVal >> 4) & 0x3, (edgeVal >> 2) & 0x3, (edgeVal >> 0) & 0x3); |
|---|
| 133 | |
|---|
| 134 | CalcIntersection(Pos[e0.x], N[e0.x], Field[e0.x], Pos[e0.y], N[e0.y], Field[e0.y]); |
|---|
| 135 | CalcIntersection(Pos[e0.z], N[e0.z], Field[e0.z], Pos[e0.w], N[e0.w], Field[e0.w]); |
|---|
| 136 | CalcIntersection(Pos[e1.x], N[e1.x], Field[e1.x], Pos[e1.y], N[e1.y], Field[e1.y]); |
|---|
| 137 | |
|---|
| 138 | // Emit additional triangle, if necessary |
|---|
| 139 | if (e1.z != -1) { |
|---|
| 140 | CalcIntersection(Pos[e1.z], N[e1.z], Field[e1.z], Pos[e1.w], N[e1.w], Field[e1.w]); |
|---|
| 141 | } |
|---|
| 142 | } |
|---|
| 143 | } |
|---|
| 144 | |
|---|
| 145 | // Pixel shader |
|---|
| 146 | float4 mainPS(float3 N : TEXCOORD0) : COLOR |
|---|
| 147 | { |
|---|
| 148 | //Sanitize input |
|---|
| 149 | N = normalize(N); |
|---|
| 150 | float3 L = float3(0, 0, 1); |
|---|
| 151 | //return float4(N*0.5+0.5, 1); |
|---|
| 152 | float3 materials[2] = { float3(1, 1, 1), float3(0, 0, 0.5)}; |
|---|
| 153 | float nDotL = dot( N, L); |
|---|
| 154 | return float4(abs(nDotL) * materials[nDotL < 0.0], 0.1); |
|---|
| 155 | } |
|---|