static float ElementShadow(Vector3 v, float rSquared, Vector3 receiverNormal, Vector3 emitterNormal, float emitterArea) { // we assume that emitterArea has already been divided by PI return((1.0f - 1.0f / SstlHelper.Sqrt(emitterArea / rSquared + 1.0f)) * SstlHelper.Clamp(Vector3.Dot(emitterNormal, v), 0f, 1.0f) * SstlHelper.Clamp(4 * Vector3.Dot(receiverNormal, v), 0f, 1.0f)); }
public static void AorThread(Mesh mesh, float[] squares, int offset, int count) { if (offset + count > mesh.Verteces.Count) { count = mesh.Verteces.Count - offset; } for (int i = offset; i < offset + count; i += 3) { var v0 = mesh.Verteces[i]; var v1 = mesh.Verteces[i + 1]; var v2 = mesh.Verteces[i + 2]; //var center1 = (v0.Position + v1.Position + v2.Position) / 3; v0.Ao = v1.Ao = v2.Ao = 1.0f; float res = 0; for (int j = 0; j < mesh.Verteces.Count; j += 3) { if (j < i || j > i + 2) { var vv0 = mesh.Verteces[j]; var vv1 = mesh.Verteces[j + 1]; var vv2 = mesh.Verteces[j + 2]; //var center2 = (vv0.Position + vv1.Position + vv2.Position) / 3; var v = vv0.Position - v0.Position; var d2 = Vector3.Dot(v, v) + 1e-16; v *= 1.0f / SstlHelper.Sqrt((float)d2); //var rsq = (center1 - center2).LengthSquared; //if (float.IsNaN(res)) //{ // continue; //} var value = ElementShadow(v, (float)d2, v0.Normal, vv0.Normal, squares[j]); if (float.IsNaN(value)) { value = 1; } res += value; if (res >= 1) { break; } // http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter14.html } } //res = SstlHelper.Clamp(res, 1, 0); v0.Ao = v1.Ao = v2.Ao = 1.0f - res; mesh.Verteces[i] = v0; mesh.Verteces[i + 1] = v1; mesh.Verteces[i + 2] = v2; AorResult += 3; } }
public void __Render(Matrix4 mvp) { if (Verteces.Count == 0) { return; } Vector3 ambient = new Vector3(0.1f, 0.1f, 0.1f); Vector3 lightVecNormalized = Vector3.Normalize(new Vector3(0.5f, 0.5f, 2)); Vector3 lightColor = new Vector3(0.7f, 0.7f, 0.7f); Vector3 lightColorRefl = new Vector3(0.7f, 0.0f, 0.0f); if (!AoTest) { GL.Begin(PrimitiveType.Triangles); for (int i = 0; i < Indeces.Count; i += 3) { VertexPositionNormalTexture v0 = Verteces[(int)Indeces[i]]; var normal = -Vector4.Transform(new Vector4(v0.Normal, 0), mvp).Xyz; float diffuse = SstlHelper.Clamp(Vector3.Dot(lightVecNormalized, Vector3.Normalize(normal)), 0.0f, 1.0f); float diffuseRefl = SstlHelper.Clamp(Vector3.Dot(lightVecNormalized, Vector3.Normalize(-normal)), 0.0f, 1.0f); var outFragColor = new Vector4(ambient + (diffuse * lightColor + diffuseRefl * lightColorRefl) * v0.Ao, 1.0f); GL.Color4(outFragColor); GL.Normal3(v0.Normal); GL.Vertex3(v0.Position); GL.Vertex3(Verteces[(int)Indeces[i + 1]].Position); GL.Vertex3(Verteces[(int)Indeces[i + 2]].Position); } GL.End(); } else { lightColor = new Vector3(0.0f, 0.0f, 0.0f); lightColorRefl = new Vector3(1.0f, 0.0f, 0.0f); GL.Begin(PrimitiveType.Triangles); for (int i = 0; i < Indeces.Count; i += 3) { VertexPositionNormalTexture v0 = Verteces[(int)Indeces[i]]; var outFragColor = new Vector4(Vector3.Lerp(lightColorRefl, lightColor, v0.Ao), 1.0f); GL.Color4(outFragColor); GL.Normal3(v0.Normal); GL.Vertex3(v0.Position); GL.Vertex3(Verteces[(int)Indeces[i + 1]].Position); GL.Vertex3(Verteces[(int)Indeces[i + 2]].Position); } GL.End(); } }
public static void AmbientOcclusionRecalc(Mesh mesh) { var squares = new float[mesh.Verteces.Count]; for (int i = 0; i < mesh.Verteces.Count; i += 3) { var v0 = mesh.Verteces[i]; var v1 = mesh.Verteces[i + 1]; var v2 = mesh.Verteces[i + 2]; var sq = SstlHelper.TriangleSquare(v0, v1, v2); squares[i] = squares[i + 1] = squares[i + 2] = sq; } AorResultTotal = mesh.Verteces.Count; AorResult = 0; int processorCount = Environment.ProcessorCount; IAsyncResult[] results = new IAsyncResult[processorCount]; var t = SstlHelper.NearestMod((int)(mesh.Verteces.Count / (float)processorCount), 3); for (int i = 0; i < processorCount; i++) { Action <Mesh, float[], int, int> aorT = AorThread; results[i] = aorT.BeginInvoke(mesh, squares, t * i, t, null, null); } while (true) { bool all = true; for (int i = 0; i < results.Length; i++) { if (!results[i].IsCompleted) { all = false; } } if (all) { break; } Thread.Sleep(300); } }
public static Mesh SmartTesselate(Mesh mesh) { Mesh m = new Mesh(); float size = 0; for (int i = 0; i < mesh.Indeces.Count; i += 3) { size += SstlHelper.TriangleSquare(mesh.Verteces[(int)mesh.Indeces[i]], mesh.Verteces[(int)mesh.Indeces[i + 1]], mesh.Verteces[(int)mesh.Indeces[i + 2]]); } size /= mesh.Indeces.Count; int off = 0; for (int i = 0; i < mesh.Indeces.Count; i += 3) { VertexPositionNormalTexture t; var sq = SstlHelper.TriangleSquare(mesh.Verteces[(int)mesh.Indeces[i]], mesh.Verteces[(int)mesh.Indeces[i + 1]], mesh.Verteces[(int)mesh.Indeces[i + 2]]); if (sq <= size * 6) { m.Verteces.Add(mesh.Verteces[(int)mesh.Indeces[i]]); m.Verteces.Add(mesh.Verteces[(int)mesh.Indeces[i + 1]]); m.Verteces.Add(mesh.Verteces[(int)mesh.Indeces[i + 2]]); m.Indeces.Add((uint)off + 0); m.Indeces.Add((uint)off + 1); m.Indeces.Add((uint)off + 2); off += 3; continue; } m.Verteces.Add(mesh.Verteces[(int)mesh.Indeces[i]]); m.Verteces.Add(mesh.Verteces[(int)mesh.Indeces[i + 1]]); m.Verteces.Add(mesh.Verteces[(int)mesh.Indeces[i + 2]]); t = (mesh.Verteces[(int)mesh.Indeces[i]] + mesh.Verteces[(int)mesh.Indeces[i + 1]]) / 2; m.Verteces.Add(t); t = (mesh.Verteces[(int)mesh.Indeces[i]] + mesh.Verteces[(int)mesh.Indeces[i + 2]]) / 2; m.Verteces.Add(t); t = (mesh.Verteces[(int)mesh.Indeces[i + 1]] + mesh.Verteces[(int)mesh.Indeces[i + 2]]) / 2; m.Verteces.Add(t); m.Indeces.Add((uint)off + 0); m.Indeces.Add((uint)off + 3); m.Indeces.Add((uint)off + 4); m.Indeces.Add((uint)off + 5); m.Indeces.Add((uint)off + 3); m.Indeces.Add((uint)off + 1); m.Indeces.Add((uint)off + 5); m.Indeces.Add((uint)off + 2); m.Indeces.Add((uint)off + 4); m.Indeces.Add((uint)off + 3); m.Indeces.Add((uint)off + 5); m.Indeces.Add((uint)off + 4); off += 6; } return(m); }