public void Draw(DrawState state) { state.PushWorldTranslateMultiply(ref this.position); if (geometry.CullTest(state)) { //draw the geometry shader.Bind(state); geometry.Draw(state); //now, if set, draw the wireframe too if (wireframeShader != null) { wireframeShader.Bind(state); //show the wireframe, disabling depth testing state.PushRenderState(); state.RenderState.DepthColourCull.DepthTestEnabled = false; //also set additive blending state.RenderState.AlphaBlend = AlphaBlendState.Additive; //set wireframe state.RenderState.DepthColourCull.FillMode = FillMode.WireFrame; //draw geometry.Draw(state); state.PopRenderState(); } } state.PopWorldMatrix(); }
private void DrawSphere(DrawState state) { //draw the geometry with a solid colour shader if (geometry.CullTest(state)) { Xen.Ex.Shaders.FillSolidColour shader = state.GetShader <Xen.Ex.Shaders.FillSolidColour>(); shader.FillColour = lightColour.ToVector4(); shader.Bind(state); geometry.Draw(state); } }
public void Draw(DrawState state) { //generate the rotation matrix for the object. Matrix basis = new Matrix(1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1); //xna_dude model is on his side state.PushWorldMatrixMultiply(ref basis); Matrix.CreateRotationZ(RotationAngle, out basis); // generate the rotation. state.PushWorldMatrixMultiply(ref basis); if (item.CullTest(state)) { item.Draw(state); } state.PopWorldMatrix(); state.PopWorldMatrix(); }
public bool CullTest(ICuller culler) { return(scene.CullTest(culler)); }
/// <summary> /// Draw the items in sorted order /// </summary> /// <param name="state"></param> public void Draw(DrawState state) { if (itemCount == 0) { return; } sortFrameIndex++; //sortEvery so many frames... if (sortFrameIndex > sortEvery) { sortFrameIndex = 0; // ok, time to sort } else { //otherwise, //draw using the previous frame sorting... if (sortMode == DepthSortMode.FrontToBack) { for (int i = 0; i < previousFrameVisibleCount; i++) { IDraw item = items[i].item; if (item.CullTest(state)) { item.Draw(state); } } } else { for (int i = previousFrameVisibleCount - 1; i >= 0; i--) { IDraw item = items[i].item; if (item.CullTest(state)) { item.Draw(state); } } } int drawn = 0; //draw the rest... for (int i = previousFrameVisibleCount; i < this.itemCount; i++) { IDraw item = items[i].item; if (item.CullTest(state)) { item.Draw(state); drawn++; } } return; } //sort and draw... ICuller culler = state; state.PushPostCuller(postCuller); postCuller.BeginPreCullItem(state); int index = 0; int visible = 0; int backIndex = itemCount - 1; int backIndexCulled = itemCount - 1; int unsortedItems = 0; Vector3 position, camera, direction; state.Camera.GetCameraPosition(out camera); state.Camera.GetCameraViewDirection(out direction); for (int i = 0; i < itemCount; i++) { Entry item = items[index]; postCuller.ResetPreCullItem(); bool cullTest = item.item.CullTest(culler); if (cullTest && postCuller.TryGetPosition(out position)) { //keep item in the list items[index] = items[visible]; //centre of cull tests position.X -= camera.X; position.Y -= camera.Y; position.Z -= camera.Z; float depth = direction.X * position.X + direction.Y * position.Y + direction.Z * position.Z; if (depth > 0) { depth = position.X * position.X + position.Y * position.Y + position.Z * position.Z; } depths[visible] = depth; items[visible] = item; visible++; index++; } else { //swap the back culled element to this one, don't increment index items[index] = items[backIndexCulled]; items[backIndexCulled] = item; backIndexCulled--; if (cullTest) { //as the last step, put this item at the very back. items[backIndexCulled + 1] = items[backIndex]; items[backIndex] = item; depths[backIndex] = item.addIndex; backIndex--; unsortedItems++; } } } state.PopPostCuller(); if (unsortedItems > 0) { backIndex++; //due to the way the algorithm works, the unsorted list is usually ordered like so: //1,2,3,4,5,6,7,0 //so put the last element first, and check if they are out of order float lastD = this.depths[this.itemCount - 1]; Entry lastE = this.items[this.itemCount - 1]; bool outOfOrder = lastD > this.depths[backIndex]; for (int i = this.itemCount - 2; i >= backIndex; i--) { if (i != this.itemCount - 2) { outOfOrder |= this.depths[i] > this.depths[i + 1]; } this.items[i + 1] = this.items[i]; this.depths[i + 1] = this.depths[i]; } this.depths[backIndex] = lastD; this.items[backIndex] = lastE; //draw the unsorted items in their add order (which was written to depths) //this sort won't be all that efficient if (outOfOrder) { Array.Sort(this.depths, this.items, backIndex, unsortedItems); } for (int i = 0; i < unsortedItems; i++) { items[backIndex++].item.Draw(state); } } if (visible > 0) { //if the frame hasn't changed, the items should already be in sorted order, //so this sort should be quick //test if the values are already sorted... float depth = this.depths[0]; bool outOfOrder = false; for (int i = 1; i < visible; i++) { outOfOrder |= depths[i] < depth; depth = depths[i]; } if (outOfOrder) { Array.Sort(this.depths, this.items, 0, visible); } if (sortMode == DepthSortMode.FrontToBack) { for (int i = 0; i < visible; i++) { items[i].item.Draw(state); } } else { for (int i = visible - 1; i >= 0; i--) { items[i].item.Draw(state); } } } previousFrameVisibleCount = visible; }
/// <summary> /// Draw the predicate, and if the predicate draws at least <see cref="MinimumPixelCount"/> pixels, the 'complex' object will be drawn /// </summary> /// <param name="state"></param> public void Draw(DrawState state) { int frame = state.FrameIndex; if (!supported || frame == frameIndex) { if (item.CullTest(state)) { item.Draw(state); } return; } if (resetOnCullChange && frameIndex != frame - 1) { //XNA requires IsComplete to be checked. if (query != null) { queryInProgress = query.IsComplete; } queryInProgress = false; //reset the query queryPixelCount = ushort.MaxValue; } if (queryInProgress && query.IsComplete) { queryInProgress = false; this.queryPixelCount = (ushort)query.PixelCount; } if (!queryInProgress) { GraphicsDevice device = state.BeginGetGraphicsDevice(Xen.Graphics.State.StateFlag.None); //run the query if (query == null) { query = new OcclusionQuery(device); if (query.IsSupported == false) { supported = false; query.Dispose(); query = null; if (item.CullTest(state)) { item.Draw(state); } return; } } query.Begin(); state.PushRenderState(); state.RenderState.DepthColourCull.DepthWriteEnabled = false; state.RenderState.DepthColourCull.ColourWriteMask = ColorWriteChannels.None; state.RenderState.AlphaBlend = new AlphaBlendState(); predicate.Draw(state); state.PopRenderState(); query.End(); queryInProgress = true; state.EndGetGraphicsDevice(); } frameIndex = frame; if (queryPixelCount >= pixelCount && item.CullTest(state)) { item.Draw(state); } }