//constructor public SphereDrawer(Vector3 position) { //setup the sphere geometry var size = new Vector3(1,1,1); //Use the prebuilt sphere geometry class this.sphereGeometry = new Sphere(size, 32); //Setup the world matrix this.worldMatrix = Matrix.CreateTranslation(position); //Create a lighting shader with some nice looking lighting //'MaterialShader' is a prebuilt class in Xen.Ex. It is similar to the XNA BasicEffect //This class implements the IShader interface. All Xen shaders implement IShader. this.shader = new MaterialShader(); this.shader.SpecularColour = Color.LightYellow.ToVector3(); //give the material a nice sheen var lightDirection = new Vector3(0.5f,1,-0.5f); //a dramatic direction //create a light collection and add a couple of lights to it var lights = new MaterialLightCollection(); lights.AmbientLightColour = Color.CornflowerBlue.ToVector3() * 0.5f; //set the ambient lights.CreateDirectionalLight(lightDirection, Color.Gray); //add the first of two light sources lights.CreateDirectionalLight(-lightDirection, Color.DarkSlateBlue); //set the light collection used by the material shader this.shader.LightCollection = lights; }
//constructor public SphereDrawer(Vector3 position) { //setup the sphere geometry Vector3 size = new Vector3(1, 1, 1); //Use the prebuilt sphere geometry class this.sphereGeometry = new Sphere(size, 32); //Setup the world matrix this.worldMatrix = Matrix.CreateTranslation(position); //Create a lighting shader with some nice looking lighting //This is a prebuilt class in Xen.Ex. It is similar to the XNA BasicEffect //This class implements IShader. All shaders implement IShader. MaterialShader material = new MaterialShader(); Vector3 lightDirection = new Vector3(0.5f, 1, -0.5f); //a dramatic direction //create a light collection and add a couple of lights to it material.Lights = new MaterialLightCollection(); material.UsePerPixelSpecular = true; material.Lights.AmbientLightColour = Color.CornflowerBlue.ToVector3() * 0.5f; //set the ambient material.Lights.AddDirectionalLight(true, lightDirection, Color.Gray); //add the first of two light sources material.Lights.AddDirectionalLight(true, -lightDirection, Color.DarkSlateBlue); material.SpecularColour = Color.LightYellow.ToVector3(); //give the material a nice sheen //store the shader this.shader = material; }
protected override void Initialise() { Resource.EnableResourceTracking(); Camera3D camera = new Camera3D(); camera.LookAt(Vector3.Zero, new Vector3(0, 0, 5), Vector3.UnitY); //create the draw target. drawToScreen = new DrawTargetScreen(this, camera); drawToScreen.ClearBuffer.ClearColour = Color.CornflowerBlue; //create a shader to display the geometry (this is the same as tutorial 02) Vector3 lightDirection = new Vector3(1.0f, 0.5f, 0.5f); MaterialShader material = new MaterialShader(new MaterialLightCollection()); material.UsePerPixelSpecular = true; material.Lights.AmbientLightColour = Color.CornflowerBlue.ToVector3() * 0.5f; //set the ambient material.Lights.AddDirectionalLight(true, lightDirection, Color.Gray); //add the first of two light sources material.Lights.AddDirectionalLight(true, -lightDirection, Color.DarkSlateBlue); material.SpecularColour = Color.LightYellow.ToVector3(); //give the material a nice sheen //create a simpler shader to display the wireframe (and also used for the bounding cube) Xen.Ex.Shaders.FillSolidColour simpleShader = new Xen.Ex.Shaders.FillSolidColour(); simpleShader.FillColour = Vector4.One * 0.01f; Vector3 sphereSize = new Vector3(0.5f, 0.5f, 0.5f); //create the complex sphere, this will have ~100k triangles. //pass in a shader for wireframe rendering sphere = new GeometryDrawer(new Xen.Ex.Geometry.Sphere(sphereSize, 200), material, simpleShader); //create the bounding cube sphereBoundingBox = new GeometryDrawer(new Xen.Ex.Geometry.Cube(sphereSize), simpleShader, null); //create the occluding cube, and position it close to the camera cube = new GeometryDrawer(new Xen.Ex.Geometry.Cube(Vector3.One), material, null); cube.position = new Vector3(0, 0, 2.75f); //add the cube first (so it can draw first, potentially occluding the sphere) //if the cube was added second, it would have no effect, as it would draw after the sphere drawToScreen.Add(cube); //create the predicate, passing in the sphere and bounding box Xen.Ex.Scene.DrawPredicate predicate = new Xen.Ex.Scene.DrawPredicate(sphere, sphereBoundingBox); //add the DrawPredicate (the DrawPredicate draws it's children) drawToScreen.Add(predicate); //statistic overlay statOverlay = new Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay(this.UpdateManager); drawToScreen.Add(statOverlay); }
public Handle(MaterialShader material) { var bindings = material.Bind(); foreach (var handle in bindings) { if (handle.DefaultState) { DefaultBindings.Add(handle); continue; } ProcessState(handle); } }
public MaterialShader CreateShader(Dictionary <string, Texture> textures) { var assembly = typeof(MaterialShader).Assembly; var types = assembly.GetTypes(); MethodInfo createMethod = null; for (int i = 0; i < types.Length; i++) { if (types[i].IsAbstract || !types[i].IsSubclassOf(typeof(MaterialShader))) { continue; } var attributes = types[i].GetCustomAttributes(typeof(ShaderTypeAttribute), true); if (attributes != null && attributes.Length > 0) { var shaderAttribute = attributes[0] as ShaderTypeAttribute; if (shaderAttribute != null && shaderAttribute.shaderType == shaderType) { var method = types[i].GetMethod("Create", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (method != null) { createMethod = method; break; } } } } if (createMethod == null) { Log.Warn($"Shader初时化失败!未找到该类型的Shader:{shaderType}"); return(null); } MaterialShader shader = createMethod.Invoke(null, new object[] { }) as MaterialShader; if (shader == null) { return(null); } if (shaderParams != null) { for (int i = 0; i < shaderParams.Count; i++) { SceneSerialization.SetParameterToObject(shader, shaderParams[i].paramName, shaderParams[i].paramValue, textures); } } return(shader); }
public GroundDisk(ContentRegister content, float radius, MaterialLightCollection lights) { //build the disk VertexPositionNormalTexture[] vertexData = new VertexPositionNormalTexture[256]; for (int i = 0; i < vertexData.Length; i++) { //a bunch of vertices, in a circle! float angle = (float)i / (float)vertexData.Length * MathHelper.TwoPi; Vector3 position = new Vector3((float)Math.Sin(angle), (float)Math.Cos(angle), 0); vertexData[i] = new VertexPositionNormalTexture(position * radius, new Vector3(0, 0, 1), new Vector2(position.X, position.Y)); } this.vertices = new Vertices <VertexPositionNormalTexture>(vertexData); //create the material, and add to content this.material = new MaterialShader(); this.material.Lights = lights; content.Add(this); }
public TerrainManager(int width, int height, int depth, int cellWidth, int cellHeight, int cellDepth) { Initialized = false; cellsInitialized = 0; terrainDimensions = new Vector3(width, height, depth); cellDimensions = new Vector3(cellWidth, cellHeight, cellDepth); terrainCells = new VolumeDensity8[width, height, depth]; terrainCellMeshes = new TerrainCellMesh[width, height, depth]; cubicTerrain = defaultCubicTerrain; cellGap = defaultCellScale; cellGap = cubicTerrain ? defaultCellScale : defaultCellScale + (1 / cellDimensions.X); WireFrame = false; ShowBoundingBoxes = false; terrainShader = new Triplanar(); boundingBoxShader = new MaterialShader(); if (!File.Exists("PolyVoxCore.dll")) throw new FileNotFoundException("Missing PolyVoxCore.dll! Please place it in the same directory as the game executable."); }
public GeometryDrawer(Vector3 position) { //create the quad geometry = new DynamicQuadGeometry(); //setup the world matrix worldMatrix = Matrix.CreateTranslation(position); //create a basic lighting shader with some average looking lighting :-) MaterialShader material = new MaterialShader(); Vector3 lightDirection = new Vector3(-1, -1, -1); //a dramatic direction material.Lights = new MaterialLightCollection(); material.Lights.AddDirectionalLight(false, -lightDirection, Color.WhiteSmoke); material.SpecularColour = Color.LightYellow.ToVector3() * 0.5f; //Note: To use vertex colours with a MaterialShader, UseVertexColour has to be set to true material.UseVertexColour = true; this.shader = material; }
public GeometryDrawer(Vector3 position) { //NEW CODE //create the quad geometry = new QuadGeometry(); //setup the world matrix worldMatrix = Matrix.CreateTranslation(position); //create a lighting shader with some average looking lighting :-) MaterialShader material = new MaterialShader(); Vector3 lightDirection = new Vector3(0.5f, 1, -0.5f); //a less dramatic direction material.Lights = new MaterialLightCollection(); material.Lights.AmbientLightColour = Color.DarkGoldenrod.ToVector3() * 0.5f; material.Lights.AddDirectionalLight(false, -lightDirection, Color.WhiteSmoke); material.SpecularColour = Color.LightYellow.ToVector3(); //with a nice sheen material.UsePerPixelSpecular = true; this.shader = material; }
public void LoadContent(ContentState state) { this.texture = state.Load<Texture2D>("skydome/cloudMap"); this.model.ModelData = state.Load<ModelData>("skydome/dome"); MaterialShader material = new MaterialShader(); material.SpecularColour = new Vector3(1, 1, 1); material.DiffuseColour = new Vector3(0.6f, 0.6f, 0.6f); material.SpecularPower = 64; MaterialTextures textures = new MaterialTextures(); textures.TextureMap = state.Load<Texture2D>("skydome/cloudMap"); textures.TextureMapSampler = TextureSamplerState.AnisotropicHighFiltering; textures.EmissiveTextureMapSampler = TextureSamplerState.AnisotropicHighFiltering; textures.NormalMapSampler = TextureSamplerState.AnisotropicHighFiltering; material.Textures = textures; this.shader = material; }
public GroundDisk(ContentRegister content, MaterialLightCollection lights, float radius) { this.radius = radius; int vertexCount = 256; //create the vertices. Note the DiskVertex() constructor takes an angle/size DiskVertex[] verts = new DiskVertex[vertexCount]; for (int i = 0; i < vertexCount; i++) { verts[i] = new DiskVertex((i / (float)(vertexCount - 1)) * MathHelper.TwoPi, radius, 0.05f); } //create the vertex buffer this.vertices = new Vertices <DiskVertex>(verts); //create the custom material for this geometry //the light collection has been passed into the constructor, although it //could easily be changed later (by changing material.Lights) this.material = new MaterialShader(lights); //By default, per-pixel lighting in the material shader does not do //specular reflection. This is because specular nearly triples the //complexity of the lighting calculation - which makes rendering slower //and reduces the maximum number of per-pixel lights supported from 4 to 2. material.UsePerPixelSpecular = true; //give the disk really bright specular for effect material.SpecularColour = new Vector3(1, 1, 1); material.DiffuseColour = new Vector3(0.6f, 0.6f, 0.6f); material.SpecularPower = 64; //setup the texture samples to use high quality anisotropic filtering material.TextureMapSampler = TextureSamplerState.AnisotropicHighFiltering; material.NormalMapSampler = TextureSamplerState.AnisotropicLowFiltering; //load the textures for this material content.Add(this); }
public HeightFieldObject(Vector3D origin, MaterialShader shader, Vector2D size, Bitmap bitmapSrc) : base(origin, shader, -1) { this.bitmapSrc = bitmapSrc; // calculate bounds areaExtent = size; Vector2D halfSize = size * 0.5; areaStart = origin - halfSize; areaEnd = origin + halfSize; double szLen = size.Length(); radius = Math.Sqrt((szLen * szLen) + (1.1 * 1.1)) / 2; hField = HeightField.FromBitmap(bitmapSrc); onePx = new Vector2D(areaExtent.X / hField.Width, areaExtent.Y / hField.Height); this.origin.Y = 0.5; zMin = 0; zTop = 1; rectangles = new Rectangle3D[] { new Rectangle3D(new Vector3D(areaStart.X, zTop, areaStart.Y), new Vector3D(areaEnd.X, zTop, areaEnd.Y), new PlaneD(new Vector3D(0, 1, 0), -zTop)), // top new Rectangle3D(new Vector3D(areaStart.X, zMin, areaStart.Y), new Vector3D(areaEnd.X, zMin, areaEnd.Y), new PlaneD(new Vector3D(0, -1, 0), zMin)), // bottom new Rectangle3D(new Vector3D(areaStart.X, zMin, areaStart.Y), new Vector3D(areaStart.X, zTop, areaEnd.Y), new PlaneD(new Vector3D(-1, 0, 0), halfSize.X)), // left new Rectangle3D(new Vector3D(areaEnd.X, zMin, areaStart.Y), new Vector3D(areaEnd.X, zTop, areaEnd.Y), new PlaneD(new Vector3D(1, 0, 0), -halfSize.X)), // right new Rectangle3D(new Vector3D(areaStart.X, zMin, areaStart.Y), new Vector3D(areaEnd.X, zTop, areaStart.Y), new PlaneD(new Vector3D(0, 0, -1), halfSize.Y)), // front new Rectangle3D(new Vector3D(areaStart.X, zMin, areaEnd.Y), new Vector3D(areaEnd.X, zTop, areaEnd.Y), new PlaneD(new Vector3D(0, 0, 1), -halfSize.Y)), // back }; }
//constructor public SphereDrawer(Vector3 position) { //setup the sphere Vector3 size = new Vector3(1, 1, 1); //use a prebuilt sphere geometry class sphereGeometry = new Sphere(size, 32); //setup the world matrix worldMatrix = Matrix.CreateTranslation(position); //create a lighting shader with some nice looking lighting MaterialShader material = new MaterialShader(); Vector3 lightDirection = new Vector3(0.5f, 1, -0.5f); //a dramatic direction material.Lights = new MaterialLightCollection(); material.Lights.AmbientLightColour = Color.CornflowerBlue.ToVector3() * 0.5f; material.Lights.AddDirectionalLight(false, lightDirection, Color.Gray); //two light sources material.Lights.AddDirectionalLight(false, -lightDirection, Color.DarkSlateBlue); material.SpecularColour = Color.LightYellow.ToVector3(); //with a nice sheen this.shader = material; }
public PlaneSceneObject(Vector3D origin, Vector3D normal, MaterialShader shader, double radius) : base(origin, shader, radius) { plane = PlaneD.FromPointNormal(origin, normal); }
public void DrawScene(CCamera camera, int excludeEid = -1) { // TODO: Clean code below up, hard to read. Game1.Inst.GraphicsDevice.Clear(new Color(Game1.Inst.Scene.LightConfig.ClearColor)); Game1.Inst.GraphicsDevice.DepthStencilState = DepthStencilState.Default; foreach (CTransform transformComponent in Game1.Inst.Scene.GetComponents <CTransform>().Values) { transformComponent.Frame = Matrix.CreateScale(transformComponent.Scale) * transformComponent.Rotation * Matrix.CreateTranslation(transformComponent.Position); } var numDraws1 = 0; var numDraws = 0; var device = Game1.Inst.GraphicsDevice; var scene = Game1.Inst.Scene; var frustrum = camera.Frustum; foreach (var component in scene.GetComponents <C3DRenderable>()) { numDraws1++; var key = component.Key; if (key == excludeEid) { // TODO: This is originally a hack to simplify rendering of environment maps. continue; } C3DRenderable model = (C3DRenderable)component.Value; if (model.model == null) { continue; // TODO: <- Should be an error, not silent fail? } CTransform transform = (CTransform)scene.GetComponentFromEntity <CTransform>(key); Matrix[] bones = new Matrix[model.model.Bones.Count]; model.model.CopyAbsoluteBoneTransformsTo(bones); var anim = Matrix.Identity; if (model.animFn != null) { anim = model.animFn(mT); } if (Game1.Inst.Scene.EntityHasComponent <CPlayer>(key)) { var cp = (CPlayer)Game1.Inst.Scene.GetComponentFromEntity <CPlayer>(key); if (cp.HitId > 0) { var playerData = (CHit)Game1.Inst.Scene.GetComponentFromEntity <CHit>(cp.HitId); if (playerData.IsAttacking) { bones[1] *= Matrix.CreateTranslation(0.0f, 0.5f, 0f); bones[1] *= Matrix.CreateRotationX(2 * (float)Math.Sin(-playerData.AnimationProgress)); bones[1] *= Matrix.CreateTranslation(0.0f, -0.5f, 0f); } } } for (int k = 0; k < model.model.Meshes.Count; k++) { var mesh = model.model.Meshes[k]; string tag = model.model.Tag as string; // TODO: This is a really ugly hack. :-( if (tag != "Heightmap") { if (frustrum.Contains(mesh.BoundingSphere.Transform(transform.Frame)) == ContainmentType.Disjoint) { break; } } Effect lastEffect = null; for (var i = 0; i < mesh.MeshParts.Count; i++) { var part = mesh.MeshParts[i]; if (part.PrimitiveCount == 0) { continue; } MaterialShader mat = null; if (model.materials != null) { model.materials.TryGetValue(i, out mat); } var effect = mat?.mEffect ?? part.Effect; if (lastEffect != effect) { if (mat != null) { mat.CamPos = camera.Position; mat.Model = bones[mesh.ParentBone.Index] * anim * transform.Frame; mat.View = camera.View; mat.Proj = camera.Projection; mat.FogStart = Game1.Inst.Scene.LightConfig.FogStart; mat.FogEnd = Game1.Inst.Scene.LightConfig.FogEnd; mat.FogColor = Game1.Inst.Scene.LightConfig.ClearColor; mat.Prerender(); } else { SetupBasicEffect((BasicEffect)effect, camera, model, scene, transform, mesh, anim, bones[mesh.ParentBone.Index], Game1.Inst.Scene.LightConfig); } lastEffect = effect; } device.SetVertexBuffer(part.VertexBuffer); device.Indices = part.IndexBuffer; for (var j = 0; j < effect.CurrentTechnique.Passes.Count; j++) { effect.CurrentTechnique.Passes[j].Apply(); numDraws++; device.DrawIndexedPrimitives(PrimitiveType.TriangleList, part.VertexOffset, 0, part.NumVertices, part.StartIndex, part.PrimitiveCount); } } } } //-------------------- // Billboards //-------------------- device.SetVertexBuffer(mBillboardVbo); device.Indices = mBillboardIbo; var bbMat = mBillboardMat; var pass0 = bbMat.mEffect.CurrentTechnique.Passes[0]; bbMat.CamPos = camera.Position; bbMat.Proj = camera.Projection; bbMat.View = camera.View; bbMat.FogStart = scene.LightConfig.FogStart; bbMat.FogEnd = scene.LightConfig.FogEnd; bbMat.FogColor = scene.LightConfig.ClearColor; var camPos = camera.Position; var o = camPos - camera.Target; o.Normalize(); o *= 2.0f; foreach (var e in scene.GetComponents <CBillboard>()) { var bb = (CBillboard)e.Value; var bbRot = Matrix.CreateBillboard(bb.Pos, camPos + o, Vector3.Up, null); bbMat.Tex = bb.Tex; bbMat.Model = Matrix.CreateScale(bb.Scale) * bbRot; bbMat.Prerender(); pass0.Apply(); device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 4, 0, 2); } foreach (var component in scene.GetComponents <CWater>()) { var model = (C3DRenderable)component.Value; var key = component.Key; if (key == excludeEid) { // TODO: This is originally a hack to simplify rendering of environment maps. continue; } CTransform transform = (CTransform)scene.GetComponentFromEntity <CTransform>(key); Matrix[] bones = new Matrix[model.model.Bones.Count]; model.model.CopyAbsoluteBoneTransformsTo(bones); foreach (var mesh in model.model.Meshes) { foreach (ModelMeshPart part in mesh.MeshParts) { Matrix world = mesh.ParentBone.Transform * transform.Frame; part.Effect.Parameters["World"].SetValue(world); part.Effect.Parameters["View"].SetValue(camera.View); part.Effect.Parameters["Projection"].SetValue(camera.Projection); part.Effect.Parameters["CameraPosition"].SetValue(camera.Position); part.Effect.Parameters["Time"].SetValue(mT); foreach (var pass in part.Effect.CurrentTechnique.Passes) { pass.Apply(); } mesh.Draw(); } } } // - }
public GroundDisk(ContentRegister content, MaterialLightCollection lights, float radius) { this.radius = radius; int vertexCount = 256; var indices = new List<int>(); //create the vertices. Note the DiskVertex() constructor takes an angle/size var verts = new DiskVertex[vertexCount]; for (int i = 0; i < vertexCount; i++) { verts[i] = new DiskVertex((i / (float)(vertexCount - 1)) * MathHelper.TwoPi, radius, 0.05f); if (i != 0) //add the tirangle indices { indices.Add(0); indices.Add(i - 1); indices.Add(i); } } //create the vertex buffer this.vertices = new Vertices<DiskVertex>(verts); this.indices = new Indices<int>(indices); //create the custom material for this geometry //the light collection has been passed into the constructor, although it //could easily be changed later (by changing material.Lights) this.Material = new MaterialShader(lights); //give the disk really bright specular for effect Material.SpecularColour = new Vector3(1,1,1); Material.DiffuseColour = new Vector3(0.6f, 0.6f, 0.6f); Material.SpecularPower = 64; //setup the texture samples to use high quality anisotropic filtering //the textures are assigned in LoadContent Material.Textures = new MaterialTextures(); Material.Textures.TextureMapSampler = TextureSamplerState.AnisotropicHighFiltering; Material.Textures.NormalMapSampler = TextureSamplerState.AnisotropicLowFiltering; //load the textures for this material content.Add(this); }
public IDisposable Bind(MaterialShader material) { return(new Handle(material)); }
public GeometryDrawer(Vector3 position) { //NEW CODE //create the quad this.geometry = new QuadGeometry(); //setup the world matrix this.worldMatrix = Matrix.CreateTranslation(position); //create a lighting shader with some average looking lighting :-) var material = new MaterialShader(); material.SpecularColour = Color.LightYellow.ToVector3();//with a nice sheen var lightDirection = new Vector3(0.5f,1,-0.5f); //a less dramatic direction var lights = new MaterialLightCollection(); lights.AmbientLightColour = Color.DarkGoldenrod.ToVector3() * 0.5f; lights.CreateDirectionalLight(-lightDirection, Color.WhiteSmoke); material.LightCollection = lights; this.shader = material; }
public GeometryDrawer(Vector3 position) { //create the quad geometry = new DynamicQuadGeometry(); //setup the world matrix worldMatrix = Matrix.CreateTranslation(position); //create a basic lighting shader with some average looking lighting :-) MaterialShader material = new MaterialShader(); material.SpecularColour = Color.LightYellow.ToVector3() * 0.5f; Vector3 lightDirection = new Vector3(-1, -1, -1); //a dramatic direction //Note: To use vertex colours with a MaterialShader, UseVertexColour has to be set to true material.UseVertexColour = true; //create a directional light MaterialLightCollection lights = new MaterialLightCollection(); lights.CreateDirectionalLight(-lightDirection, Color.WhiteSmoke); material.LightCollection = lights; this.shader = material; }
public GroundDisk(ContentRegister content, float radius, MaterialLightCollection lights) { //build the disk var vertexData = new VertexPositionNormalTexture[256]; var indices = new List<int>(); for (int i = 1; i < vertexData.Length; i++) { //a bunch of vertices, in a circle! float angle = (float)(i-1) / (float)(vertexData.Length-2) * MathHelper.TwoPi; Vector3 position = new Vector3((float)Math.Sin(angle), (float)Math.Cos(angle), 0); vertexData[i] = new VertexPositionNormalTexture(position * radius, new Vector3(0, 0, 1), new Vector2(position.X, position.Y)); if (i > 1) { indices.Add(0); indices.Add(i - 1); indices.Add(i); } } vertexData[0] = new VertexPositionNormalTexture(new Vector3(), new Vector3(0, 0, 1), new Vector2()); this.vertices = new Vertices<VertexPositionNormalTexture>(vertexData); this.indices = new Indices<int>(indices); //create the material, and add to content this.material = new MaterialShader(); this.material.LightCollection = lights; this.material.Textures = new MaterialTextures(); content.Add(this); }
//constructor public SphereDrawer(Vector3 position) { //setup the sphere var size = new Vector3(1,1,1); //use a prebuilt sphere geometry class sphereGeometry = new Sphere(size, 32); //setup the world matrix worldMatrix = Matrix.CreateTranslation(position); //create a lighting shader with some nice looking lighting var material = new MaterialShader(); material.SpecularColour = Color.LightYellow.ToVector3();//with a nice sheen var lightDirection = new Vector3(0.5f,1,-0.5f); //a dramatic direction var lights = new MaterialLightCollection(); lights.AmbientLightColour = Color.CornflowerBlue.ToVector3() * 0.5f; lights.CreateDirectionalLight(lightDirection, Color.Gray);//two light sources lights.CreateDirectionalLight(-lightDirection, Color.DarkSlateBlue); material.LightCollection = lights; this.shader = material; }
/// <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> /// Draw all the model batch instances /// </summary> /// <param name="state"></param> public void Draw(DrawState state) { if (modelData == null) { throw new InvalidOperationException("ModelData is null"); } if (geometry == null) { SetupGeometry(); } int geometryIndex = 0; BatchModelShaderProvider 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) { shaderProvider.BeginDraw(state); } //loop through the model data for (int m = 0; m < modelData.meshes.Length; m++) { MeshData mesh = modelData.meshes[m]; if (shaderProvider != null) { shaderProvider.BeginMesh(state, mesh); } for (int g = 0; g < mesh.geometry.Length; g++) { GeometryData geom = mesh.geometry[g]; GeometrySet set = this.geometry[geometryIndex]; if (set.count > 0) { bool instancing = state.SupportsHardwareInstancing && set.count > 2; if (shaderProvider == null || !shaderProvider.BeginGeometryShaderOverride(state, geom, lights, instancing)) { MaterialShader shader = geom.MaterialShader; shader.AnimationTransforms = null; shader.UseHardwareInstancing = instancing; shader.Lights = lights; shader.Bind(state); } //draw the geometry if (instancing) { state.DrawBatch(geom.Vertices, geom.Indices, PrimitiveType.TriangleList, null, set.instances, set.count); } else { for (int i = 0; i < set.count; i++) { state.PushWorldMatrixMultiply(ref set.instances[i]); geom.Vertices.Draw(state, geom.Indices, PrimitiveType.TriangleList); state.PopWorldMatrix(); } } if (shaderProvider != null) { shaderProvider.EndGeometry(state, geom); } } set.count = 0; geometryIndex++; } if (shaderProvider != null) { shaderProvider.EndMesh(state, mesh); } } if (shaderProvider != null) { shaderProvider.EndDraw(state); } drawCount = 0; }
protected override void Initialise() { Camera3D camera = new Camera3D(); camera.LookAt(Vector3.Zero, new Vector3(0, 0, 5), Vector3.UnitY); //create the draw target. drawToScreen = new DrawTargetScreen(camera); drawToScreen.ClearBuffer.ClearColour = Color.CornflowerBlue; //create a shader to display the geometry (this is the same as tutorial 02) var lightDirection = new Vector3(1.0f, 0.5f, 0.5f); var material = new MaterialShader(); material.SpecularColour = Color.LightYellow.ToVector3(); //give the material a nice sheen var lights = new MaterialLightCollection(); lights.AmbientLightColour = Color.CornflowerBlue.ToVector3() * 0.5f; //set the ambient lights.CreateDirectionalLight(lightDirection, Color.Gray); //add the first of two light sources lights.CreateDirectionalLight(-lightDirection, Color.DarkSlateBlue); material.LightCollection = lights; //create a simpler shader to display the wireframe (and also used for the bounding cube) var simpleShader = new Xen.Ex.Shaders.FillSolidColour(); simpleShader.FillColour = Vector4.One * 0.01f; var sphereSize = new Vector3(0.5f, 0.5f, 0.5f); //create the complex sphere, this will have ~100k triangles. //pass in a shader for wireframe rendering sphere = new GeometryDrawer(new Xen.Ex.Geometry.Sphere(sphereSize, 200), material, simpleShader); //create the bounding cube sphereBoundingBox = new GeometryDrawer(new Xen.Ex.Geometry.Cube(sphereSize), simpleShader, null); //create the occluding cube, and position it close to the camera cube = new GeometryDrawer(new Xen.Ex.Geometry.Cube(Vector3.One), material, null); cube.position = new Vector3(0, 0, 2.75f); //add the cube first (so it can draw first, potentially occluding the sphere) //if the cube was added second, it would have no effect, as it would draw after the sphere drawToScreen.Add(cube); //create the predicate, passing in the sphere and bounding box var predicate = new Xen.Ex.Scene.DrawPredicate(sphere, sphereBoundingBox); //add the DrawPredicate (the DrawPredicate draws it's children) drawToScreen.Add(predicate); //statistic overlay statOverlay = new Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay(this.UpdateManager); drawToScreen.Add(statOverlay); }