/// <summary></summary> /// <param name="shaderProvider"></param> public ShaderProviderFlag(ModelInstanceShaderProvider shaderProvider) { this.overrideShaderProvider = true; if (shaderProvider != null && shaderProvider.ProviderModifiesWorldMatrixInBeginDraw) { throw new ArgumentException("shaderProvider.ProviderModifiesWorldMatrixInBeginDraw cannot be true for ShaderProviderFlag"); } this.shaderProvider = shaderProvider; }
/// <summary> /// Draw the model. This class automatically assigns shaders when drawing /// </summary> /// <param name="state"></param> public void Draw(DrawState state) { if (modelData == null) { throw new InvalidOperationException("ModelData is null"); } if (controller != null) { controller.WaitForAsyncAnimation(state, state.FrameIndex, true); if (controller.IsDisposed) { controller = null; } } if (controller != null && hierarchy == null) { hierarchy = new MaterialAnimationTransformHierarchy(modelData.skeleton); } if (hierarchy != null) { hierarchy.UpdateTransformHierarchy(controller.transformedBones); } ModelInstanceShaderProvider shaderProvider = this.shaderProvider; MaterialLightCollection lights = this.lights; ShaderProviderFlag providerFlag; MaterialLightCollection.LightCollectionFlag lightsFlag; state.GetDrawFlag(out providerFlag); if (providerFlag.OverrideShaderProvider) { shaderProvider = providerFlag.ShaderProvider; } state.GetDrawFlag(out lightsFlag); if (lightsFlag.OverrideLightCollection) { lights = lightsFlag.LightCollection; } if (shaderProvider != null) { if (controller != null) { shaderProvider.BeginDraw(state, controller.transformedBones, hierarchy.GetMatrixData()); } else { shaderProvider.BeginDraw(state); } } Vector3 boundsMin, boundsMax; ContainmentType cullModel = ContainmentType.Contains; //if there is just one geometry object, then the ICullable.CullTest() call will have been suficient. bool skipCullTest = this.modelData != null && this.modelData.meshes.Length == 1 && this.modelData.meshes[0].geometry.Length == 1; if (!skipCullTest) { if (controller != null) { cullModel = state.Culler.IntersectBox(ref controller.boundsMin, ref controller.boundsMax); } else { cullModel = state.Culler.IntersectBox(ref modelData.staticBounds.minimum, ref modelData.staticBounds.maximum); } } if (cullModel != ContainmentType.Disjoint) { for (int m = 0; m < modelData.meshes.Length; m++) { MeshData mesh = modelData.meshes[m]; if (shaderProvider != null) { shaderProvider.BeginMesh(state, mesh); } ContainmentType cullMesh = cullModel; if (cullModel == ContainmentType.Intersects && modelData.meshes.Length > 1) { if (controller != null) { controller.ComputeMeshBounds(m, out boundsMin, out boundsMax); cullMesh = state.Culler.IntersectBox(ref boundsMin, ref boundsMax); } else { cullMesh = state.Culler.IntersectBox(ref mesh.staticBounds.minimum, ref mesh.staticBounds.maximum); } } if (cullMesh != ContainmentType.Disjoint) { for (int g = 0; g < mesh.geometry.Length; g++) { GeometryData geom = mesh.geometry[g]; MaterialShader shader = geom.MaterialShader; if (shaderProvider != null && shaderProvider.BeginGeometryShaderOverride(state, geom, lights)) { shader = null; } bool cullTest = true; if (cullMesh == ContainmentType.Intersects && mesh.geometry.Length > 1) { if (controller != null) { controller.ComputeGeometryBounds(m, g, out boundsMin, out boundsMax); cullTest = state.Culler.TestBox(ref boundsMin, ref boundsMax); } else { cullTest = state.Culler.TestBox(ref geom.staticBounds.minimum, ref geom.staticBounds.maximum); } } if (cullTest) { if (shader != null) { shader.AnimationTransforms = hierarchy; shader.Lights = lights; shader.Bind(state); } geom.Vertices.Draw(state, geom.Indices, PrimitiveType.TriangleList); } if (shaderProvider != null) { shaderProvider.EndGeometry(state, geom); } } } if (shaderProvider != null) { shaderProvider.EndMesh(state, mesh); } } } if (shaderProvider != null) { shaderProvider.EndDraw(state); } }
/// <summary> /// Extend the <see cref="ModelInstanceShaderProvider"/> abstract class to override shaders or world matrices used by this model instance /// </summary> /// <param name="provider"></param> public void SetShaderOverride(ModelInstanceShaderProvider provider) { shaderProvider = provider; }