//!!!! //!!!!need per camera context //double smoothIntensityFactorLastUpdate; //double? smoothIntensityFactor; ///////////////////////////////////////// protected override void OnRender(ViewportRenderingContext context, Component_RenderingPipeline.IFrameData frameData, ref Component_Image actualTexture) { base.OnRender(context, frameData, ref actualTexture); var cameraSettings = context.Owner.CameraSettings; bool lightFound = false; Vector3 lightPosition = Vector3.Zero; if (OverrideDirection.Value != Vector3.Zero) { lightFound = true; lightPosition = cameraSettings.Position - OverrideDirection.Value.GetNormalize() * cameraSettings.FarClipDistance; } else { if (Light.ReferenceSpecified) { var light = Light.Value; if (light != null) { lightFound = true; if (light.Type.Value == Component_Light.TypeEnum.Directional) { lightPosition = cameraSettings.Position - light.TransformV.Rotation.GetForward() * cameraSettings.FarClipDistance; } else { lightPosition = light.TransformV.Position; } } } else { var frameData2 = frameData as Component_RenderingPipeline_Basic.FrameData; if (frameData2 != null) { foreach (var lightIndex in frameData2.LightsInFrustumSorted) { var item = frameData2.Lights[lightIndex]; if (item.data.Type == Component_Light.TypeEnum.Directional) { lightFound = true; lightPosition = cameraSettings.Position - item.data.Rotation.GetForward() * (float)cameraSettings.FarClipDistance; break; } } } } } if (!lightFound) { return; } if (!context.Owner.CameraSettings.ProjectToScreenCoordinates(lightPosition, out var screenLightPosition)) { return; } //calculate intensity factor by the sun position on the screen. double demandIntensityFactor = 0; { Degree angle = 0; if (lightPosition != cameraSettings.Position) { angle = MathAlgorithms.GetVectorsAngle(cameraSettings.Rotation.GetForward(), (lightPosition - cameraSettings.Position).GetNormalize()).InDegrees(); } else { angle = 10000; } var curve = new CurveLine(); curve.AddPoint(0, new Vector3(1, 0, 0)); curve.AddPoint(60, new Vector3(1, 0, 0)); curve.AddPoint(75, new Vector3(0, 0, 0)); curve.AddPoint(90, new Vector3(0, 0, 0)); var angleFactor = curve.CalculateValueByTime(angle).X; var curve2 = new CurveLine(); curve2.AddPoint(-0.2, new Vector3(0, 0, 0)); curve2.AddPoint(-0.1, new Vector3(1, 0, 0)); curve2.AddPoint(1.1, new Vector3(1, 0, 0)); curve2.AddPoint(1.2, new Vector3(0, 0, 0)); var heightFactor = curve2.CalculateValueByTime(screenLightPosition.Y).X; demandIntensityFactor = angleFactor * heightFactor; //const float screenFadingBorder = .1f; //double minDistance = 1; //for( int axis = 0; axis < 2; axis++ ) //{ // if( screenLightPosition[ axis ] < screenFadingBorder ) // { // var d = screenLightPosition[ axis ]; // if( d < minDistance ) // minDistance = d; // } // else if( screenLightPosition[ axis ] > 1.0f - screenFadingBorder ) // { // var d = 1.0f - screenLightPosition[ axis ]; // if( d < minDistance ) // minDistance = d; // } //} //needIntensityFactor = minDistance / screenFadingBorder; //MathEx.Saturate( ref needIntensityFactor ); ////clamp screenLightPosition //if( !new Rectangle( 0, 0, 1, 1 ).Contains( screenLightPosition ) ) //{ // if( MathAlgorithms.IntersectRectangleLine( new Rectangle( .0001f, .0001f, .9999f, .9999f ), // new Vector2( .5f, .5f ), screenLightPosition, out var intersectPoint1, out var intersectPoint2 ) != 0 ) // { // screenLightPosition = intersectPoint1; // } //} } var smoothIntensityFactor = demandIntensityFactor; ////update smooth intensity factor //if( smoothIntensityFactor == null ) // smoothIntensityFactor = needIntensityFactor; //if( smoothIntensityFactorLastUpdate != context.Owner.LastUpdateTime ) //{ // smoothIntensityFactorLastUpdate = context.Owner.LastUpdateTime; // const double smoothSpeed = 1; // var step = context.Owner.LastUpdateTimeStep * smoothSpeed; // if( needIntensityFactor > smoothIntensityFactor ) // { // smoothIntensityFactor += step; // if( smoothIntensityFactor > needIntensityFactor ) // smoothIntensityFactor = needIntensityFactor; // } // else // { // smoothIntensityFactor -= step; // if( smoothIntensityFactor < needIntensityFactor ) // smoothIntensityFactor = needIntensityFactor; // } //} //get result intensity var resultIntensity = Intensity.Value * smoothIntensityFactor; if (resultIntensity <= 0) { return; } double divisor = 9.0 - Resolution; if (divisor <= 1) { divisor = 1; } var sizeFloat = actualTexture.Result.ResultSize.ToVector2() / divisor; var size = new Vector2I((int)sizeFloat.X, (int)sizeFloat.Y); //scattering pass var scatteringTexture = context.RenderTarget2D_Alloc(size, PixelFormat.A8R8G8B8); //!!!! PixelFormat.R8G8B8 ); { context.SetViewport(scatteringTexture.Result.GetRenderTarget().Viewports[0]); CanvasRenderer.ShaderItem shader = new CanvasRenderer.ShaderItem(); shader.VertexProgramFileName = @"Base\Shaders\EffectsCommon_vs.sc"; shader.FragmentProgramFileName = @"Base\Shaders\Effects\LightShafts\Scattering_fs.sc"; context.objectsDuringUpdate.namedTextures.TryGetValue("depthTexture", out var depthTexture); if (depthTexture == null) { //!!!! } shader.Parameters.Set(new ViewportRenderingContext.BindTextureData(0 /*"depthTexture"*/, depthTexture, TextureAddressingMode.Clamp, FilterOption.Point, FilterOption.Point, FilterOption.None)); shader.Parameters.Set("screenLightPosition", screenLightPosition.ToVector2F()); shader.Parameters.Set("decay", (float)Decay); shader.Parameters.Set("density", (float)Density); context.RenderQuadToCurrentViewport(shader); } //blur pass var blurTexture = context.RenderTarget2D_Alloc(size, PixelFormat.A8R8G8B8); //!!!! PixelFormat.R8G8B8 ); { context.SetViewport(blurTexture.Result.GetRenderTarget().Viewports[0]); CanvasRenderer.ShaderItem shader = new CanvasRenderer.ShaderItem(); shader.VertexProgramFileName = @"Base\Shaders\EffectsCommon_vs.sc"; shader.FragmentProgramFileName = @"Base\Shaders\Effects\LightShafts\Blur_fs.sc"; //!!!!Linear? shader.Parameters.Set(new ViewportRenderingContext.BindTextureData(0 /*"scatteringTexture"*/, scatteringTexture, TextureAddressingMode.Clamp, FilterOption.Linear, FilterOption.Linear, FilterOption.None)); shader.Parameters.Set("color", Color.Value.ToVector3F()); shader.Parameters.Set("screenLightPosition", screenLightPosition.ToVector2F()); shader.Parameters.Set("blurFactor", (float)BlurFactor); context.RenderQuadToCurrentViewport(shader); } //free old textures context.DynamicTexture_Free(scatteringTexture); //create final var finalTexture = context.RenderTarget2D_Alloc(actualTexture.Result.ResultSize, actualTexture.Result.ResultFormat); { context.SetViewport(finalTexture.Result.GetRenderTarget().Viewports[0]); CanvasRenderer.ShaderItem shader = new CanvasRenderer.ShaderItem(); shader.VertexProgramFileName = @"Base\Shaders\EffectsCommon_vs.sc"; shader.FragmentProgramFileName = @"Base\Shaders\Effects\LightShafts\Final_fs.sc"; shader.Parameters.Set(new ViewportRenderingContext.BindTextureData(0 /*"sourceTexture"*/, actualTexture, TextureAddressingMode.Clamp, FilterOption.Point, FilterOption.Point, FilterOption.None)); shader.Parameters.Set(new ViewportRenderingContext.BindTextureData(1 /*"blurTexture"*/, blurTexture, TextureAddressingMode.Clamp, FilterOption.Linear, FilterOption.Linear, FilterOption.None)); shader.Parameters.Set("intensity", (float)resultIntensity); context.RenderQuadToCurrentViewport(shader); } //free old textures context.DynamicTexture_Free(actualTexture); context.DynamicTexture_Free(blurTexture); //update actual texture actualTexture = finalTexture; }
public static void GenerateTorus(int axis, double radius, int segments, Degree circumference, double tubeRadius, int tubeSegments, Degree tubeCircumference, /*bool smooth, */ bool insideOut, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces) { if (radius < tubeRadius) { tubeRadius = radius; } bool loopOfLegs = Math.Abs(circumference.ToDouble() - 360) < 1e-5; bool endCapes = !loopOfLegs; if (radius <= 0 || tubeRadius <= 0 || segments < 3 || tubeSegments < 3 || circumference <= 0 || tubeCircumference <= 0) { GetEmptyData(out positions, out normals, out tangents, out texCoords, out indices, out faces); return; } ReplaceAxes(out int axis0, out int axis1, axis); int nextVertex = 0; Point[] polygon = GenerateCircleZ(tubeSegments + 1, tubeRadius, tubeCircumference, ref nextVertex); FromZAxisToAxis(polygon, axis0); //сечение тора Matrix4[] m = GetTransformsOfRotationCircle(segments + 1, axis, circumference, (radius - tubeRadius) * GetAxisVector(axis1)); var legs = GenerateLegs(polygon, m, nextVertex, loopOfLegs); int rawVertexCount = CommonPipeBuilder.GetLegsRawVertexCount(legs) + (endCapes ? 2 * CommonPipeBuilder.GetPolygonAdaptiveRawVertexCount(polygon) : 0); var builder = new CommonPipeBuilder(rawVertexCount, (legs.Length - 1) * tubeSegments + (endCapes ? 2 : 0), true); builder.AddLegs(legs, insideOut, 1); //ToDo ?? Нужны ли крышки когда circumference<360 ? Может опцию endCapes ? //Add capes if (endCapes) { nextVertex *= legs.Length; Point center0 = new Point(m[0] * Vector3.Zero, nextVertex++); Point center1 = new Point(m[m.Length - 1] * Vector3.Zero, nextVertex++); builder.AddPolygonAdaptive(legs[0], center0, !insideOut, !insideOut); //normal противоположна от направления смещения legs поэтому !insideOut builder.AddPolygonAdaptive(legs[legs.Length - 1], center1, insideOut, insideOut); } builder.GetData(out positions, out normals, out tangents, out texCoords, out indices, out faces); }
public static void GenerateTorus(int axis, double radius, int segments, Degree circumference, double tubeRadius, int tubeSegments, Degree tubeCircumference, /*bool smooth, */ bool insideOut, out Vector3F[] positions, out Vector3F[] normals, out Vector4F[] tangents, out Vector2F[] texCoords, out int[] indices, out Face[] faces) { GenerateTorus(axis, radius, segments, circumference, tubeRadius, tubeSegments, tubeCircumference, /*smooth, */ insideOut, out Vector3[] positionsD, out Vector3[] normalsD, out Vector4[] tangentsD, out Vector2[] texCoordsD, out indices, out faces);
public static Degree Generate(Degree minValue, Degree maxValue) { lock (_static) return(_static.Next(minValue, maxValue)); }
public static void GenerateArch(int axis, double radius, double thickness, double depth, int segments, int segmentsDepth, Degree circumference, bool endCapes, bool insideOut, out Vector3F[] positions, out Vector3F[] normals, out Vector4F[] tangents, out Vector2F[] texCoords, out int[] indices, out Face[] faces) { GenerateArch(axis, radius, thickness, depth, segments, segmentsDepth, circumference, endCapes, insideOut, out Vector3[] positionsD, out Vector3[] normalsD, out Vector4[] tangentsD, out Vector2[] texCoordsD, out indices, out faces);
//ToDo : Логичнее когда главное направление для оси, в направлении входа. При axis=1,2 арка стоит, при axis=2 лежит на боку - тогда задать default axis=2 //ToDo ??? Надо ли сделать чтобы нижние поверхности были паралельны земле при circumference<180 ?(тогда угол у внутреннего кольца будет меньше). public static void GenerateArch(int axis, double radius, double thickness, double depth, int segments, int segmentsDepth, Degree circumference, bool endCapes, bool insideOut, out Vector3[] positions, out Vector3[] normals, out Vector4[] tangents, out Vector2[] texCoords, out int[] indices, out Face[] faces) { if (radius < thickness) { thickness = radius; } if (radius <= 0 || segments < 2 || segmentsDepth < 0 || circumference <= 0) { GetEmptyData(out positions, out normals, out tangents, out texCoords, out indices, out faces); return; } //ToDo ??? endCapes это передняя/задняя или нижние поверхности ? bool frontBack = endCapes && 1e-8 < thickness; bool bottom = endCapes; int legPointCount = segments + 1; int nextVertex = 0; double startAngle = ((Math.PI - circumference.InRadians()) / 2); Point[] outer = GenerateCircleZ(legPointCount, radius, circumference, ref nextVertex, startAngle); FromZAxisToAxis(outer, axis); Point[] inner = GenerateCircleZ(legPointCount, radius - thickness, circumference, ref nextVertex, startAngle); FromZAxisToAxis(inner, axis); Point[] down1 = { inner[0], outer[0] }; Point[] down2 = { outer[outer.Length - 1], inner[inner.Length - 1] }; var halfVector = 0.5 * depth * GetAxisVector(axis); Matrix4[] m = GetTransformsOfLinePath(segmentsDepth + 1, -halfVector, halfVector); var legsOuter = GenerateLegs(outer, m, nextVertex, false); var legsInner = GenerateLegs(inner, m, nextVertex, false); Point[][] legsDown1 = null; Point[][] legsDown2 = null; if (bottom) { legsDown1 = GenerateLegs(down1, m, nextVertex, false); legsDown2 = GenerateLegs(down2, m, nextVertex, false); } int rawVertexCount = 2 * CommonPipeBuilder.GetLegsRawVertexCount(legsOuter) + (legsDown1 == null ? 0 : 2 * CommonPipeBuilder.GetLegsRawVertexCount(legsDown1)) + (frontBack ? 2 * CommonPipeBuilder.GetPolygon2RawVertexCount(outer) : 0); int faceCount = 2 * segments * (legsOuter.Length - 1) + 2 * (bottom ? legsOuter.Length - 1 : 0) + (frontBack ? 2 : 0); var builder = new CommonPipeBuilder(rawVertexCount, faceCount, true); builder.AddLegs(legsOuter, insideOut, 1); builder.AddLegs(legsInner, !insideOut, 1); if (bottom) { builder.AddLegs(legsDown1, insideOut); builder.AddLegs(legsDown2, insideOut); } if (frontBack) { builder.AddPolygon2(legsOuter[0], legsInner[0], !insideOut, !insideOut); //normal противоположна от направления смещения legs поэтому !insideOut builder.AddPolygon2(legsOuter[legsOuter.Length - 1], legsInner[legsInner.Length - 1], insideOut, insideOut); } builder.GetData(out positions, out normals, out tangents, out texCoords, out indices, out faces); }