/// <summary> /// Class level dispose method /// </summary> /// <remarks> /// When implementing this method in an inherited class the following template should be used; /// protected override void dispose( bool disposeManagedResources ) /// { /// if ( !isDisposed ) /// { /// if ( disposeManagedResources ) /// { /// // Dispose managed resources. /// } /// /// // There are no unmanaged resources to release, but /// // if we add them, they need to be released here. /// } /// /// // If it is available, make the call to the /// // base class's Dispose(Boolean) method /// base.dispose( disposeManagedResources ); /// } /// </remarks> /// <param name="disposeManagedResources">True if Unmanaged resources should be released.</param> protected override void dispose(bool disposeManagedResources) { if (!IsDisposed) { if (disposeManagedResources) { // Dispose managed resources. if (this.renderOperation != null) { if (!this.renderOperation.IsDisposed) { this.renderOperation.Dispose(); } this.renderOperation = null; } if (this.material != null) { if (!this.material.IsDisposed) { this.material.Dispose(); } this.material = null; } } // There are no unmanaged resources to release, but // if we add them, they need to be released here. } base.dispose(disposeManagedResources); }
/// <summary> /// Gets the render operation for this shadow renderable. /// </summary> /// <param name="op"></param> public void GetRenderOperation(RenderOperation op) { // TODO: Ensure all other places throughout the engine set these properly op.indexData = renderOp.indexData; op.useIndices = true; op.operationType = OperationType.TriangleList; op.vertexData = renderOp.vertexData; }
public override void GetRenderOperation(RenderOperation op) { // LineLists never use indices op.useIndices = false; op.indexData = null; // set the operation type op.operationType = OperationType.LineList; // set the vertex data correctly op.vertexData = vertexData; }
public override void GetRenderOperation(RenderOperation op) { ValidateBrush(); op.useIndices = true; op.operationType = OperationType.TriangleList; if (rebuildVertex) { buildVertexData(); rebuildVertex = false; } op.vertexData = vertexData; if (rebuildIndex) { buildIndexData(); rebuildIndex = false; } op.indexData = indexData; }
/// <summary> /// Gets the render operation required to send this object to the frame buffer. /// </summary> public void GetRenderOperation(RenderOperation op) { }
/// <summary> /// Class level dispose method /// </summary> /// <remarks> /// When implementing this method in an inherited class the following template should be used; /// protected override void dispose( bool disposeManagedResources ) /// { /// if ( !isDisposed ) /// { /// if ( disposeManagedResources ) /// { /// // Dispose managed resources. /// } /// /// // There are no unmanaged resources to release, but /// // if we add them, they need to be released here. /// } /// /// // If it is available, make the call to the /// // base class's Dispose(Boolean) method /// base.dispose( disposeManagedResources ); /// } /// </remarks> /// <param name="disposeManagedResources">True if Unmanaged resources should be released.</param> protected override void dispose( bool disposeManagedResources ) { if ( !IsDisposed ) { if ( disposeManagedResources ) { // Dispose managed resources. if ( renderOperation != null ) { if (!this.renderOperation.IsDisposed) this.renderOperation.Dispose(); renderOperation = null; } if (indexData != null) { if (!indexData.IsDisposed) indexData.Dispose(); indexData = null; } if (vertexData != null) { if (!vertexData.IsDisposed) vertexData.Dispose(); vertexData = null; } } // There are no unmanaged resources to release, but // if we add them, they need to be released here. } base.dispose(disposeManagedResources); }
public override void GetRenderOperation(RenderOperation op) { Debug.Assert(inBoundary); Debug.Assert(renderOp.vertexData != null, "attempting to render heightField with no vertexData"); Debug.Assert(renderOp.indexData != null, "attempting to render heightField with no indexData"); op.useIndices = this.renderOp.useIndices; op.operationType = this.renderOp.operationType; op.vertexData = this.renderOp.vertexData; op.indexData = this.renderOp.indexData; }
/// Gets all the patches within an AABB in world coordinates as GeometryData structs public virtual void GetRenderOpsInBox( AxisAlignedBox box, ArrayList opList) { if ( MathUtil.Intersects(box, bounds ) != Intersection.None ) { RenderOperation rend = new RenderOperation(); renderable.GetRenderOperation( rend ); opList.Add( rend ); } }
public TerrainPage(Vector3 location, Page page) { this.location = location; pageCoord = new PageCoord(location, TerrainManager.Instance.PageSize); terrainMaterial = TerrainManager.Instance.TerrainMaterialConfig.NewTerrainMaterial(pageCoord.X, pageCoord.Z); currentPage = page; Debug.Assert(location == currentPage.Location, "creating TerrainPage with page at different location"); numTiles = currentPage.NumTiles; patchSize = TerrainManager.Instance.PageSize / numTiles; // set up the page height maps for this page of terrain subPageSize = TerrainManager.Instance.SubPageSize; int subPagesPerPage = TerrainManager.Instance.PageSize / subPageSize; pageHeightMap = new PageHeightMap(subPagesPerPage, TerrainManager.Instance.PageSize, TerrainManager.Instance.MaxMetersPerSample, TerrainManager.Instance.MinMetersPerSample); pageHeightMap.Location = location; // create and position a scene node for this terrain page string nodeName = String.Format("TerrainPage[{0},{1}]", (int)(location.x / TerrainManager.oneMeter), (int)(location.z / TerrainManager.oneMeter)); // DEBUG - Console.WriteLine("Creating {0}", name); sceneNode = TerrainManager.Instance.WorldRootSceneNode.CreateChildSceneNode(nodeName); sceneNode.Position = location; sceneNode.AttachObject(this); // create the render operation renderOp = new RenderOperation(); renderOp.operationType = OperationType.TriangleList; renderOp.useIndices = true; CreatePatches(); SetCastShadows(); UpdateBounds(); TerrainManager.Instance.ShadowConfig.ShadowTechniqueChange += ShadowTechniqueChangeHandler; }
/// <summary> /// Internal utility method for rendering a single object. /// </summary> /// <param name="renderable">The renderable to issue to the pipeline.</param> /// <param name="pass">The pass which is being used.</param> /// <param name="doLightIteration">If true, this method will issue the renderable to /// the pipeline possibly multiple times, if the pass indicates it should be /// done once per light.</param> /// <param name="manualLightList">Only applicable if 'doLightIteration' is false, this /// method allows you to pass in a previously determined set of lights /// which will be used for a single render of this object.</param> protected virtual void RenderSingleObject( IRenderable renderable, Pass pass, bool doLightIteration, LightList manualLightList ) { ushort numMatrices = 0; // grab the current scene detail level PolygonMode camPolyMode = this.cameraInProgress.PolygonMode; // get the world matrices and the count renderable.GetWorldTransforms( this.xform ); numMatrices = renderable.NumWorldTransforms; // set the world matrices in the render system if ( numMatrices > 1 ) { this.targetRenderSystem.SetWorldMatrices( this.xform, numMatrices ); } else { this.targetRenderSystem.WorldMatrix = this.xform[ 0 ]; } // issue view/projection changes (if any) this.UseRenderableViewProjection( renderable ); if ( !this.suppressRenderStateChanges ) { bool passSurfaceAndLightParams = true; if ( pass.IsProgrammable ) { // Tell auto params object about the renderable change this.autoParamDataSource.Renderable = renderable; pass.UpdateAutoParamsNoLights( this.autoParamDataSource ); if ( pass.HasVertexProgram ) { passSurfaceAndLightParams = pass.VertexProgram.PassSurfaceAndLightStates; } } // issue texture units that depend on updated view matrix // reflective env mapping is one case for ( int i = 0; i < pass.TextureUnitStageCount; i++ ) { TextureUnitState texUnit = pass.GetTextureUnitState( i ); if ( texUnit.HasViewRelativeTexCoordGen ) { targetRenderSystem.SetTextureUnitSettings( i, texUnit ); //this.targetRenderSystem.SetTextureUnit( i, texUnit, !pass.HasFragmentProgram ); } } // Normalize normals bool thisNormalize = renderable.NormalizeNormals; if ( thisNormalize != normalizeNormals ) { this.targetRenderSystem.NormalizeNormals = thisNormalize; normalizeNormals = thisNormalize; } // Set up the solid / wireframe override PolygonMode requestedMode = pass.PolygonMode; if ( renderable.PolygonModeOverrideable == true ) { // check camera detial only when render detail is overridable if ( requestedMode > camPolyMode ) { // only downgrade detail; if cam says wireframe we don't go up to solid requestedMode = camPolyMode; } } if ( requestedMode != this.lastPolyMode ) { this.targetRenderSystem.PolygonMode = requestedMode; this.lastPolyMode = requestedMode; } // TODO: Add ClipPlanes to RenderSystem.cs // This is removed in OGRE 1.6.0... no need to port - J. Price //targetRenderSystem.ClipPlanes = renderable.ClipPlanes; // get the renderables render operation op = renderable.RenderOperation; // TODO: Add srcRenderable to RenderOperation.cs //op.srcRenderable = renderable; if ( doLightIteration ) { // Here's where we issue the rendering operation to the render system // Note that we may do this once per light, therefore it's in a loop // and the light parameters are updated once per traversal through the // loop LightList rendLightList = renderable.Lights; bool iteratePerLight = pass.IteratePerLight; int numIterations = iteratePerLight ? rendLightList.Count : 1; LightList lightListToUse = null; for ( int i = 0; i < numIterations; i++ ) { // determine light list to use if ( iteratePerLight ) { localLightList.Clear(); // check whether we need to filter this one out if ( pass.RunOnlyOncePerLightType && pass.OnlyLightType != rendLightList[ i ].Type ) { // skip this one continue; } localLightList.Add( rendLightList[ i ] ); lightListToUse = localLightList; } else { // use complete light list lightListToUse = rendLightList; } if ( pass.IsProgrammable ) { // Update any automatic gpu params for lights // Other bits of information will have to be looked up this.autoParamDataSource.SetCurrentLightList( lightListToUse ); pass.UpdateAutoParamsLightsOnly( this.autoParamDataSource ); UpdateGpuProgramParameters( pass ); } // Do we need to update light states? // Only do this if fixed-function vertex lighting applies if ( pass.LightingEnabled && passSurfaceAndLightParams ) { this.targetRenderSystem.UseLights( lightListToUse, pass.MaxSimultaneousLights ); } this.targetRenderSystem.CurrentPassIterationCount = pass.IterationCount; // issue the render op this.targetRenderSystem.Render( op ); } // iterate per light } else { // do we need to update GPU program parameters? if ( pass.IsProgrammable ) { // do we have a manual light list if ( manualLightList != null ) { // Update any automatic gpu params for lights // Other bits of information will have to be looked up this.autoParamDataSource.SetCurrentLightList( manualLightList ); pass.UpdateAutoParamsLightsOnly( this.autoParamDataSource ); } UpdateGpuProgramParameters( pass ); } // Use manual lights if present, and not using vertex programs if ( manualLightList != null && pass.LightingEnabled && passSurfaceAndLightParams ) { this.targetRenderSystem.UseLights( manualLightList, pass.MaxSimultaneousLights ); } this.targetRenderSystem.CurrentPassIterationCount = pass.IterationCount; // issue the render op this.targetRenderSystem.Render( op ); } } else { // suppressRenderStateChanges // Just render this.targetRenderSystem.CurrentPassIterationCount = 1; this.targetRenderSystem.Render( op ); } // Reset view / projection changes if any this.ResetViewProjectionMode(); }
/// <summary> /// Class level dispose method /// </summary> /// <remarks> /// When implementing this method in an inherited class the following template should be used; /// protected override void dispose( bool disposeManagedResources ) /// { /// if ( !isDisposed ) /// { /// if ( disposeManagedResources ) /// { /// // Dispose managed resources. /// } /// /// // There are no unmanaged resources to release, but /// // if we add them, they need to be released here. /// } /// /// // If it is available, make the call to the /// // base class's Dispose(Boolean) method /// base.dispose( disposeManagedResources ); /// } /// </remarks> /// <param name="disposeManagedResources">True if Unmanaged resources should be released.</param> protected virtual void dispose( bool disposeManagedResources ) { if ( !isDisposed ) { if ( disposeManagedResources ) { // Dispose managed resources. if ( renderOperation != null ) { renderOperation.vertexData = null; renderOperation.indexData = null; renderOperation = null; } } // There are no unmanaged resources to release, but // if we add them, they need to be released here. } isDisposed = true; }
/// <summary> /// Render something to the active viewport. /// </summary> /// <remarks> /// Low-level rendering interface to perform rendering /// operations. Unlikely to be used directly by client /// applications, since the <see cref="SceneManager"/> and various support /// classes will be responsible for calling this method. /// Can only be called between BeginScene and EndScene /// </remarks> /// <param name="op"> /// A rendering operation instance, which contains details of the operation to be performed. /// </param> public override void Render(RenderOperation op) { //StateManager.RasterizerState.FillMode = XFG.FillMode.Solid; StateManager.CommitState(_device); #if SILVERLIGHT StateManager.ResetState(_device); #endif Effect effectToUse; if (useSkinnedEffect) { var boneMatrices = new Matrix[Root.Instance.SceneManager.AutoParamData.WorldMatrixCount]; for (var i = 0; i < Root.Instance.SceneManager.AutoParamData.WorldMatrixCount; i++) { #if!(XBOX || XBOX360) boneMatrices[i] = XnaHelper.Convert(Root.Instance.SceneManager.AutoParamData.WorldMatrixArray[i]); #else Axiom.Math.Matrix4 matrix = Root.Instance.SceneManager.AutoParamData.WorldMatrixArray[i]; boneMatrices[i] = XnaHelper.Convert( matrix ); #endif } skinnedEffect.SetBoneTransforms(boneMatrices); effectToUse = skinnedEffect; } else { basicEffect.VertexColorEnabled = op.vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Diffuse) != null; basicEffect.TextureEnabled = op.vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.TexCoords) != null; effectToUse = basicEffect; } var ve = op.vertexData.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Normal); if (ve != null) //this operation has Normals { basicEffect.LightingEnabled = false; //turn off lighting } basicEffect.LightingEnabled = (ve != null); //Debug.WriteLine(" Vertices=" + op.vertexData.vertexCount + // " Normals=" + (ve != null) + // " Lighting=" + basicEffect.LightingEnabled + // " DL0=" + basicEffect.DirectionalLight0.Enabled + // " Fog=" + basicEffect.FogEnabled + // " " + effectToUse); // effectToUse.CurrentTechnique.Passes[0].Apply(); //DualTextureEffect dualTextureEffect; // don't even bother if there are no vertices to render, causes problems on some cards (FireGL 8800));) if (op.vertexData.vertexCount == 0) { return; } // class base implementation first base.Render(op); /*---------------shaders generator part------*/ #if AXIOM_FF_EMULATION if ( Root.Instance.RenderSystem.ConfigOptions[ "Use Content Pipeline" ].Value != "Yes" ) { if ( !VertexShaderIsSet || !PixelShaderIsSet ) { FixedFunctionEmulation.VertexBufferDeclaration vbd = new FixedFunctionEmulation.VertexBufferDeclaration(); List<FixedFunctionEmulation.VertexBufferElement> lvbe = new List<FixedFunctionEmulation.VertexBufferElement>( op.vertexData.vertexDeclaration.ElementCount ); int textureLayer = 0; for ( int i = 0; i < op.vertexData.vertexDeclaration.ElementCount; i++ ) { FixedFunctionEmulation.VertexBufferElement element = new FixedFunctionEmulation.VertexBufferElement(); element.VertexElementIndex = (ushort)op.vertexData.vertexDeclaration[ i ].Index; element.VertexElementSemantic = op.vertexData.vertexDeclaration[ i ].Semantic; element.VertexElementType = op.vertexData.vertexDeclaration[ i ].Type; //uncomment this to see the texture shadow //the problem is that some texcoords are given but texture is not set // /*if (//op.vertexData.vertexDeclaration[i].Type == VertexElementType.Float1 && op.vertexData.vertexDeclaration[ i ].Semantic == VertexElementSemantic.TexCoords ) { if ( !texStageDesc[ textureLayer ].Enabled ) { texStageDesc[ textureLayer ].layerBlendMode = new LayerBlendModeEx(); texStageDesc[ textureLayer ].layerBlendMode.blendType = LayerBlendType.Color; texStageDesc[ textureLayer ].layerBlendMode.operation = LayerBlendOperationEx.Modulate; texStageDesc[ textureLayer ].layerBlendMode.source1 = LayerBlendSource.Texture; texStageDesc[ textureLayer ].layerBlendMode.source2 = LayerBlendSource.Current; texStageDesc[ textureLayer ].Enabled = true; //texStageDesc[ textureLayer ].autoTexCoordType = TexCoordCalcMethod.ProjectiveTexture; texStageDesc[ textureLayer ].coordIndex = textureLayer; switch ( op.vertexData.vertexDeclaration[ i ].Type ) { case VertexElementType.Float1: texStageDesc[ textureLayer ].texType = TextureType.OneD; break; case VertexElementType.Float2: texStageDesc[ textureLayer ].texType = TextureType.TwoD; break; case VertexElementType.Float3: texStageDesc[ textureLayer ].texType = TextureType.ThreeD; break; } //texStageDesc[textureLayer].layerBlendMode = new LayerBlendModeEx(); } textureLayer++; }*/ lvbe.Add( element ); } vbd.VertexBufferElements = lvbe; for ( int i = 0; i < Config.MaxTextureLayers; i++ ) { FixedFunctionEmulation.TextureLayerState tls = new FixedFunctionEmulation.TextureLayerState(); if ( texStageDesc[ i ].Enabled ) //if (texStageDesc[i].tex != null) { tls.TextureType = texStageDesc[ i ].texType; tls.TexCoordCalcMethod = texStageDesc[ i ].autoTexCoordType; tls.CoordIndex = texStageDesc[ i ].coordIndex; tls.LayerBlendMode = texStageDesc[ i ].layerBlendMode; //TextureLayerStateList _fixedFunctionState.TextureLayerStates.Add( tls ); } FixedFunctionEmulation.GeneralFixedFunctionState gff; gff = _fixedFunctionState.GeneralFixedFunctionState; gff.EnableLighting = _ffProgramParameters.LightingEnabled; gff.FogMode = _ffProgramParameters.FogMode; _fixedFunctionState.GeneralFixedFunctionState = gff; //lights foreach ( Light l in _ffProgramParameters.Lights ) _fixedFunctionState.Lights.Add( l.Type ); _fixedFunctionProgram = (FixedFunctionEmulation.HLSLFixedFunctionProgram)_shaderManager.GetShaderPrograms( "hlsl", vbd, _fixedFunctionState ); _fixedFunctionProgram.FragmentProgramUsage.Program.DefaultParameters.NamedParamCount.ToString(); _fixedFunctionProgram.SetFixedFunctionProgramParameters( _ffProgramParameters ); //Bind Vertex Program if ( !VertexShaderIsSet ) { BindGpuProgram( _fixedFunctionProgram.VertexProgramUsage.Program.BindingDelegate ); BindGpuProgramParameters( GpuProgramType.Vertex, _fixedFunctionProgram.VertexProgramUsage.Params ); needToUnmapVS = true; } // Bind Fragment Program if ( !PixelShaderIsSet ) { BindGpuProgram( _fixedFunctionProgram.FragmentProgramUsage.Program.BindingDelegate ); BindGpuProgramParameters( GpuProgramType.Fragment, _fixedFunctionProgram.FragmentProgramUsage.Params ); needToUnmapFS = true; } //clear parameters lists for next frame _fixedFunctionState.Lights.Clear(); _fixedFunctionState.TextureLayerStates.Clear(); //_fixedFunctionState.MaterialEnabled = false; //_ffProgramParameters.FogMode = FogMode.None; } } } /*---------------------------------------------------------------------------------------------------------*/ #endif var vertDecl = (XnaVertexDeclaration)op.vertexData.vertexDeclaration; // set the vertex declaration and buffer binding //_device.VertexDeclaration = vertDecl.XnaVertexDecl; _setVertexBufferBinding(op.vertexData.vertexBufferBinding); PrimitiveType primType = 0; switch (op.operationType) { case OperationType.PointList: primType = PrimitiveType.LineList; /* XNA 4.0 doesn't support PointList so using LineList instead */ primCount = op.useIndices ? op.indexData.indexCount : op.vertexData.vertexCount; break; case OperationType.LineList: primType = PrimitiveType.LineList; primCount = (op.useIndices ? op.indexData.indexCount : op.vertexData.vertexCount) / 2; break; case OperationType.LineStrip: primType = PrimitiveType.LineStrip; primCount = (op.useIndices ? op.indexData.indexCount : op.vertexData.vertexCount) - 1; break; case OperationType.TriangleList: primType = PrimitiveType.TriangleList; primCount = (op.useIndices ? op.indexData.indexCount : op.vertexData.vertexCount) / 3; break; case OperationType.TriangleStrip: primType = PrimitiveType.TriangleStrip; primCount = (op.useIndices ? op.indexData.indexCount : op.vertexData.vertexCount) - 2; break; case OperationType.TriangleFan: throw new Exception("XNA 4.0 doesn't support TriangleFan"); } // switch(primType) try { // are we gonna use indices? if (op.useIndices) { var idxBuffer = (XnaHardwareIndexBuffer)op.indexData.indexBuffer; _device.Indices = idxBuffer.XnaIndexBuffer; foreach (var pass in effectToUse.CurrentTechnique.Passes) { pass.Apply(); _device.DrawIndexedPrimitives(primType, op.vertexData.vertexStart, 0, op.vertexData.vertexCount, op.indexData.indexStart, primCount); } } else { // draw vertices without indices foreach (var pass in effectToUse.CurrentTechnique.Passes) { pass.Apply(); _device.DrawPrimitives(primType, op.vertexData.vertexStart, primCount); } } } catch (InvalidOperationException ioe) { LogManager.Instance.Write("Failed to draw RenderOperation : ", LogManager.BuildExceptionString(ioe)); } //crap hack, set the sources back to null to allow accessing vertices and indices buffers _device.SetVertexBuffer(null); _device.Indices = null; _device.Textures[0] = null; #if AXIOM_FF_EMULATION /*---------------shaders generator part------*/ if ( needToUnmapVS ) { UnbindGpuProgram( GpuProgramType.Vertex ); } if ( needToUnmapFS ) { UnbindGpuProgram( GpuProgramType.Fragment ); } /*--------------------------------------------*/ #endif }
/// <summary> /// Returns the geometry to use during rendering. /// </summary> /// <param name="op"></param> public override void GetRenderOperation(Axiom.Graphics.RenderOperation op) { op.vertexData = renderOp.vertexData; op.operationType = renderOp.operationType; op.useIndices = renderOp.useIndices; }
/// <summary> /// Overloaded method. /// </summary> /// <param name="op"></param> /// <returns></returns> public void GetRenderOperation( RenderOperation op ) { // call overloaded method with lod index of 0 by default GetRenderOperation( op, 0 ); }
public void ManualRender( RenderOperation op, Pass pass, Viewport vp, Matrix4 worldMatrix, Matrix4 viewMatrix, Matrix4 projMatrix ) { this.ManualRender( op, pass, vp, worldMatrix, viewMatrix, projMatrix, false ); }
/// <summary> /// generates renderOps from billboards. nulls billboards when done. /// </summary> public void FinishRebuild() { foreach (string textureName in billboards.Keys) { foreach (int alpha in billboards[textureName].Keys) { List<float[]>bbList = billboards[textureName][alpha]; RenderOperation renderOp = new RenderOperation(); renderOp.operationType = OperationType.TriangleList; renderOp.useIndices = false; VertexData vertexData = new VertexData(); vertexData.vertexCount = 6 * bbList.Count; vertexData.vertexStart = 0; // free the original vertex declaration to avoid a leak HardwareBufferManager.Instance.DestroyVertexDeclaration(vertexData.vertexDeclaration); // use common vertex declaration vertexData.vertexDeclaration = TreeGroup.BillboardVertexDeclaration; // create the hardware vertex buffer and set up the buffer binding HardwareVertexBuffer hvBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( vertexData.vertexDeclaration.GetVertexSize(0), vertexData.vertexCount, BufferUsage.StaticWriteOnly, false); vertexData.vertexBufferBinding.SetBinding(0, hvBuffer); renderOp.vertexData = vertexData; // lock the vertex buffer IntPtr ipBuf = hvBuffer.Lock(BufferLocking.Discard); int bufferOff = 0; unsafe { float* buffer = (float*)ipBuf.ToPointer(); foreach (float[] src in bbList) { buffer[bufferOff++] = src[0]; buffer[bufferOff++] = src[1]; buffer[bufferOff++] = src[2]; buffer[bufferOff++] = src[3]; buffer[bufferOff++] = src[4]; buffer[bufferOff++] = src[5]; buffer[bufferOff++] = src[6]; buffer[bufferOff++] = src[7]; buffer[bufferOff++] = src[8]; buffer[bufferOff++] = src[9]; buffer[bufferOff++] = src[10]; buffer[bufferOff++] = src[11]; buffer[bufferOff++] = src[12]; buffer[bufferOff++] = src[13]; buffer[bufferOff++] = src[14]; buffer[bufferOff++] = src[10]; buffer[bufferOff++] = src[11]; buffer[bufferOff++] = src[12]; buffer[bufferOff++] = src[13]; buffer[bufferOff++] = src[14]; buffer[bufferOff++] = src[15]; buffer[bufferOff++] = src[16]; buffer[bufferOff++] = src[17]; buffer[bufferOff++] = src[18]; buffer[bufferOff++] = src[19]; buffer[bufferOff++] = src[0]; buffer[bufferOff++] = src[1]; buffer[bufferOff++] = src[2]; buffer[bufferOff++] = src[3]; buffer[bufferOff++] = src[4]; } } hvBuffer.Unlock(); TreeBillboardRenderOp op = new TreeBillboardRenderOp(textureName, alpha, renderOp); renderOps.Add(op); } } billboards = null; }
public override void GetRenderOperation(RenderOperation op) { op.vertexData = vertexData; op.useIndices = false; op.operationType = OperationType.TriangleStrip; }
public void GetRenderOperation(RenderOperation op) { throw new NotImplementedException(); }
/// <summary> /// /// </summary> /// <param name="op"></param> public abstract void GetRenderOperation(RenderOperation op);
public TreeBillboardRenderOp(string textureName, int alpha, RenderOperation renderOp) { this.textureName = textureName; this.alpha = alpha; this.renderOp = renderOp; }
public void BoundaryChange() { Debug.Assert(inBoundary); DisposeBuffers(); renderOp = null; BuildBuffers(); }
protected override void dispose( bool disposeManagedResources ) { if ( !IsDisposed ) { if ( disposeManagedResources ) { if ( SceneManagerDestroyed != null ) { SceneManagerDestroyed( this ); } ClearScene(); RemoveAllCameras(); if ( op != null ) { if ( !op.IsDisposed ) { op.Dispose(); } op = null; } if ( this.autoParamDataSource != null ) { if ( !this.autoParamDataSource.IsDisposed ) { this.autoParamDataSource.Dispose(); } this.autoParamDataSource = null; } if ( this.rootSceneNode != null ) { if ( !this.rootSceneNode.IsDisposed ) { this.rootSceneNode.Dispose(); } this.rootSceneNode = null; } } } base.dispose( disposeManagedResources ); }
private void BuildBuffers() { // // Build the vertex buffer // List<Vector2> points = boundary.Points; List<int[]> indices = boundary.Triangles; VertexData vertexData = new VertexData(); vertexData.vertexCount = boundary.Points.Count; vertexData.vertexStart = 0; // set up the vertex declaration int vDecOffset = 0; vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float3, VertexElementSemantic.Position); vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float3); vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float3, VertexElementSemantic.Normal); vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float3); vertexData.vertexDeclaration.AddElement(0, vDecOffset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0); vDecOffset += VertexElement.GetTypeSize(VertexElementType.Float2); // create the hardware vertex buffer and set up the buffer binding HardwareVertexBuffer hvBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( vertexData.vertexDeclaration.GetVertexSize(0), vertexData.vertexCount, BufferUsage.StaticWriteOnly, false); vertexData.vertexBufferBinding.SetBinding(0, hvBuffer); // lock the vertex buffer IntPtr ipBuf = hvBuffer.Lock(BufferLocking.Discard); int bufferOff = 0; float minx = boundary.Bounds.Minimum.x; float minz = boundary.Bounds.Minimum.z; unsafe { float* buffer = (float*)ipBuf.ToPointer(); for (int v = 0; v < vertexData.vertexCount; v++) { // Position buffer[bufferOff++] = points[v].x; buffer[bufferOff++] = height; buffer[bufferOff++] = points[v].y; // normals buffer[bufferOff++] = 0; buffer[bufferOff++] = 1; buffer[bufferOff++] = 0; // Texture float tmpu = ( points[v].x - minx ) / (128 * TerrainManager.oneMeter); float tmpv = ( points[v].y - minz )/ (128 * TerrainManager.oneMeter); buffer[bufferOff++] = tmpu; buffer[bufferOff++] = tmpv; } } hvBuffer.Unlock(); // // build the index buffer // IndexData indexData = new IndexData(); int numIndices = indices.Count * 3; indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, numIndices, BufferUsage.StaticWriteOnly); IntPtr indexBufferPtr = indexData.indexBuffer.Lock(0, indexData.indexBuffer.Size, BufferLocking.Discard); unsafe { ushort* indexBuffer = (ushort*)indexBufferPtr.ToPointer(); for (int i = 0; i < indices.Count; i++) { indexBuffer[i * 3] = (ushort)indices[i][0]; indexBuffer[i * 3 + 1] = (ushort)indices[i][1]; indexBuffer[i * 3 + 2] = (ushort)indices[i][2]; } } indexData.indexBuffer.Unlock(); indexData.indexCount = numIndices; indexData.indexStart = 0; renderOp = new RenderOperation(); renderOp.vertexData = vertexData; renderOp.indexData = indexData; renderOp.operationType = OperationType.TriangleList; renderOp.useIndices = true; }
protected override void dispose( bool disposeManagedResources ) { if ( !IsDisposed ) { if ( disposeManagedResources ) { // Dispose managed resources. if ( renderOperation != null ) { renderOperation.vertexData = null; renderOperation.indexData = null; renderOperation = null; } } } base.dispose( disposeManagedResources ); }
public override void Render( RenderOperation op ) { GLES2Config.GlCheckError( this ); base.Render( op ); var bufferData = 0; var decl = op.vertexData.vertexDeclaration.Elements; var gles2decl = op.vertexData.vertexDeclaration as GLES2VertexDeclaration; // Use a little shorthand #if !AXIOM_NO_GLES2_VAO_SUPPORT bool useVAO = ( null != gles2decl && gles2decl.IsInitialized() ); #else bool useVAO = false; #endif if ( useVAO ) SetVertexDeclaration( op.vertexData.vertexDeclaration, op.vertexData.vertexBufferBinding ); foreach ( var elem in decl ) { var elemIndex = elem.Index; var elemSource = elem.Source; var elemType = elem.Type; if ( !op.vertexData.vertexBufferBinding.IsBufferBound( elemSource ) ) { continue; //skip unbound elements } GLES2Config.GlCheckError( this ); HardwareVertexBuffer vertexBuffer = op.vertexData.vertexBufferBinding.GetBuffer( elemSource ); this.BindGLBuffer( GLenum.ArrayBuffer, ( vertexBuffer as GLES2HardwareVertexBuffer ).GLBufferID ); if ( !useVAO || ( useVAO && null != gles2decl && !gles2decl.IsInitialized ) ) { bufferData = elem.Offset; VertexElementSemantic sem = elem.Semantic; var typeCount = VertexElement.GetTypeCount( elemType ); bool normalized = false; int attrib = 0; if ( op.vertexData.vertexStart != 0 ) { bufferData = bufferData + op.vertexData.vertexStart & vertexBuffer.VertexSize; } if ( Capabilities.HasCapability( Graphics.Capabilities.SeperateShaderObjects ) ) { GLSLESProgramPipeline programPipeline = GLSLESProgramPipelineManager.Instance.ActiveProgramPipeline; if ( !programPipeline.IsAttributeValid( sem, elemIndex ) ) { continue; } attrib = programPipeline.GetAttributeIndex( sem, elemIndex ); } else { GLSLESLinkProgram linkProgram = GLSLESLinkProgramManager.Instance.ActiveLinkProgram; if ( null == linkProgram || !linkProgram.IsAttributeValid( sem, elemIndex ) ) { continue; } attrib = linkProgram.GetAttributeIndex( sem, elemIndex ); } switch ( elem.Type ) { case VertexElementType.Color: case VertexElementType.Color_ARGB: case VertexElementType.Color_ABGR: //Because GL takes these as a sequence of single unsigned bytes, count needs to be 4 //VertexElement.GetTypeCount treams them as 1 (RGBA) //Also need to normalize the fixed-point data typeCount = 4; normalized = true; break; default: break; } GL.VertexAttribPointer( attrib, typeCount, GLES2HardwareBufferManager.GetGLType( elemType ), normalized, vertexBuffer.VertexSize, ref bufferData ); GLES2Config.GlCheckError( this ); GL.EnableVertexAttribArray( attrib ); GLES2Config.GlCheckError( this ); this.renderAttribsBound.Add( attrib ); } } //Find the correct type to render GLenum primType = GLenum.TriangleFan; switch ( op.operationType ) { case OperationType.PointList: primType = GLenum.Points; break; case OperationType.LineList: primType = GLenum.Lines; break; case OperationType.LineStrip: primType = GLenum.LineStrip; break; case OperationType.TriangleList: primType = GLenum.Triangles; break; case OperationType.TriangleStrip: primType = GLenum.TriangleStrip; break; case OperationType.TriangleFan: primType = GLenum.TriangleFan; break; } if ( op.useIndices ) { // If we are using VAO's then only bind the buffer the first time through. Otherwise, always bind. if (!useVAO || ( useVAO && null != gles2decl && !gles2decl.IsInitialized ) ) this.BindGLBuffer( GLenum.ElementArrayBuffer, ((GLES2HardwareIndexBuffer )op.indexData.indexBuffer).BufferID ); bufferData = op.indexData.indexStart * op.indexData.indexBuffer.IndexSize; GLenum indexType = ( op.indexData.indexBuffer.Type == IndexType.Size16 ) ? GLenum.UnsignedShort : GLenum.UnsignedInt; do { //Update derived depth bias if ( derivedDepthBias && currentPassIterationCount > 0 ) { this.SetDepthBias( derivedDepthBiasBase + derivedDepthBiasMultiplier * currentPassIterationNum, derivedDepthBiasSlopeScale ); } GLES2Config.GlCheckError( this ); GL.DrawElements( ( this.polygonMode == GLenum.PolygonOffsetFill ) ? primType : this.polygonMode, op.indexData.indexCount, indexType, ref bufferData ); GLES2Config.GlCheckError( this, false ); } while ( UpdatePassIterationRenderState() ); } else { do { //Update derived depth bias if ( derivedDepthBias && currentPassIterationNum > 0 ) { this.SetDepthBias( derivedDepthBiasBase + derivedDepthBiasMultiplier * currentPassIterationNum, derivedDepthBiasSlopeScale ); } GLES2Config.GlCheckError( this ); //GL.DrawArrays( ( this.polygonMode == GLenum.PolygonOffsetFill ) ? primType : this.polygonMode, 0, op.vertexData.vertexCount ); GL.DrawArrays( All.Triangles, 0, op.vertexData.vertexCount ); GLES2Config.GlCheckError( this, false ); } while ( UpdatePassIterationRenderState() ); } //Unbind all attributes foreach ( var ai in this.renderAttribsBound ) { GL.DisableVertexAttribArray( ai ); GLES2Config.GlCheckError( this ); } this.renderAttribsBound.Clear(); }
public override void Render( RenderOperation op ) { // Exit immediately if there is nothing to render // This caused a problem on FireGL 8800 if ( op.vertexData.vertexCount == 0 ) { return; } base.Render( op ); // To think about: possibly remove setVertexDeclaration and // setVertexBufferBinding from RenderSystem since the sequence is // a bit too D3D9-specific? VertexDeclaration = op.vertexData.vertexDeclaration; // TODO: the false parameter has to be carried inside op as var SetVertexBufferBinding(op.vertexData.vertexBufferBinding, op.numberOfInstances, false, op.useIndices); // Determine rendering operation var primType = PrimitiveType.TriangleList; var lprimCount = op.vertexData.vertexCount; var cnt = op.useIndices && primType != PrimitiveType.PointList ? op.indexData.indexCount : op.vertexData.vertexCount; switch ( op.operationType ) { case OperationType.TriangleList: primType = PrimitiveType.TriangleList; lprimCount = cnt / 3; break; case OperationType.TriangleStrip: primType = PrimitiveType.TriangleStrip; lprimCount = cnt - 2; break; case OperationType.TriangleFan: primType = PrimitiveType.TriangleFan; lprimCount = cnt - 2; break; case OperationType.PointList: primType = PrimitiveType.PointList; lprimCount = cnt; break; case OperationType.LineList: primType = PrimitiveType.LineList; lprimCount = cnt / 2; break; case OperationType.LineStrip: primType = PrimitiveType.LineStrip; lprimCount = cnt - 1; break; } // switch(primType) if (lprimCount == 0) return; if (op.useIndices) { var d3DIdxBuf = (D3DHardwareIndexBuffer)op.indexData.indexBuffer; ActiveD3D9Device.Indices = d3DIdxBuf.D3DIndexBuffer; do { // Update derived depth bias if (derivedDepthBias && currentPassIterationNum > 0) { SetDepthBias(derivedDepthBiasBase + derivedDepthBiasMultiplier * currentPassIterationNum, derivedDepthBiasSlopeScale); } // draw the indexed primitives ActiveD3D9Device.DrawIndexedPrimitives(primType, op.vertexData.vertexStart, 0, op.vertexData.vertexCount, op.indexData.indexStart, lprimCount); } while (UpdatePassIterationRenderState()); } else { // nfz: gpu_iterate do { // Update derived depth bias if (derivedDepthBias && currentPassIterationNum > 0) { SetDepthBias(derivedDepthBiasBase + derivedDepthBiasMultiplier * currentPassIterationNum, derivedDepthBiasSlopeScale); } // Unindexed, a little simpler! ActiveD3D9Device.DrawPrimitives(primType, op.vertexData.vertexStart, lprimCount); } while (UpdatePassIterationRenderState()); } }
/// <summary> /// Class level dispose method /// </summary> /// <remarks> /// When implementing this method in an inherited class the following template should be used; /// protected override void dispose( bool disposeManagedResources ) /// { /// if ( !isDisposed ) /// { /// if ( disposeManagedResources ) /// { /// // Dispose managed resources. /// } /// /// // There are no unmanaged resources to release, but /// // if we add them, they need to be released here. /// } /// /// // If it is available, make the call to the /// // base class's Dispose(Boolean) method /// base.dispose( disposeManagedResources ); /// } /// </remarks> /// <param name="disposeManagedResources">True if Unmanaged resources should be released.</param> protected override void dispose( bool disposeManagedResources ) { if ( !IsDisposed ) { if ( disposeManagedResources ) { // Dispose managed resources. if ( renderOperation != null ) { if (!renderOperation.IsDisposed) renderOperation.Dispose(); renderOperation = null; } } // There are no unmanaged resources to release, but // if we add them, they need to be released here. } base.dispose(disposeManagedResources); }
/// <summary> /// Internal constructor, only allows creation of StitchRenderables within the scene manager. /// </summary> internal StitchRenderable(TerrainPatch terrainPatch, VertexData vertexData, IndexData indexData, int numSamples, int southMetersPerSample, int eastMetersPerSample) { renderDetail = SceneDetailLevel.Solid; parent = terrainPatch; renderOp = new RenderOperation(); renderOp.operationType = OperationType.TriangleList; renderOp.useIndices = true; renderOp.vertexData = vertexData; renderOp.indexData = indexData; isVisible = true; this.numSamples = numSamples; this.southMetersPerSample = southMetersPerSample; this.eastMetersPerSample = eastMetersPerSample; }
/// <summary> /// Fills a RenderOperation structure required to render this mesh. /// </summary> /// <param name="op">Reference to a RenderOperation structure to populate.</param> /// <param name="lodIndex">The index of the LOD to use.</param> public void GetRenderOperation( RenderOperation op, int lodIndex ) { // meshes always use indices op.useIndices = true; // use lod face list if requested, else pass the normal face list if ( lodIndex > 0 && ( lodIndex - 1 ) < this.lodFaceList.Count ) { // Use the set of indices defined for this LOD level op.indexData = this.lodFaceList[ lodIndex - 1 ]; } else { op.indexData = this.indexData; } // set the operation type op.operationType = this.operationType; // set the vertex data correctly op.vertexData = this.useSharedVertices ? this.parent.SharedVertexData : this.vertexData; }
/// <summary> /// /// </summary> /// <param name="op"></param> public void GetRenderOperation(RenderOperation op) { Debug.Assert(renderOp.vertexData != null, "attempting to render stitch with no vertexData"); Debug.Assert(renderOp.indexData != null, "attempting to render stitch with no indexData"); op.useIndices = this.renderOp.useIndices; op.operationType = this.renderOp.operationType; op.vertexData = this.renderOp.vertexData; op.indexData = this.renderOp.indexData; }
/// <summary> /// Manual rendering method, for advanced users only. /// </summary> /// <remarks> /// This method allows you to send rendering commands through the pipeline on /// demand, bypassing any normal world processing. You should only use this if you /// really know what you're doing; the engine does lots of things for you that you really should /// let it do. However, there are times where it may be useful to have this manual interface, /// for example overlaying something on top of the scene. /// <p/> /// Because this is an instant rendering method, timing is important. The best /// time to call it is from a RenderTarget event handler. /// <p/> /// Don't call this method a lot, it's designed for rare (1 or 2 times per frame) use. /// Calling it regularly per frame will cause frame rate drops! /// </remarks> /// <param name="op">A RenderOperation object describing the rendering op.</param> /// <param name="pass">The Pass to use for this render.</param> /// <param name="vp">Reference to the viewport to render to.</param> /// <param name="worldMatrix">The transform to apply from object to world space.</param> /// <param name="viewMatrix">The transform to apply from object to view space.</param> /// <param name="projMatrix">The transform to apply from view to screen space.</param> /// <param name="doBeginEndFrame"> /// If true, BeginFrame() and EndFrame() are called, otherwise not. /// You should leave this as false if you are calling this within the main render loop. /// </param> public virtual void ManualRender( RenderOperation op, Pass pass, Viewport vp, Matrix4 worldMatrix, Matrix4 viewMatrix, Matrix4 projMatrix, bool doBeginEndFrame ) { // configure all necessary parameters this.targetRenderSystem.Viewport = vp; this.targetRenderSystem.WorldMatrix = worldMatrix; this.targetRenderSystem.ViewMatrix = viewMatrix; this.targetRenderSystem.ProjectionMatrix = projMatrix; if ( doBeginEndFrame ) { this.targetRenderSystem.BeginFrame(); } // set the pass and render the object this.SetPass( pass ); this.targetRenderSystem.Render( op ); if ( doBeginEndFrame ) { this.targetRenderSystem.EndFrame(); } }
/// <summary> /// Generates the indexes required to render a shadow volume into the /// index buffer which is passed in, and updates shadow renderables to use it. /// </summary> /// <param name="edgeData">The edge information to use.</param> /// <param name="indexBuffer">The buffer into which to write data into; current /// contents are assumed to be discardable.</param> /// <param name="light">The light, mainly for type info as silhouette calculations /// should already have been done in <see cref="UpdateEdgeListLightFacing"/></param> /// <param name="shadowRenderables">A list of shadow renderables which has /// already been constructed but will need populating with details of /// the index ranges to be used.</param> /// <param name="flags">Additional controller flags, see <see cref="ShadowRenderableFlags"/>.</param> protected virtual void GenerateShadowVolume(EdgeData edgeData, HardwareIndexBuffer indexBuffer, Light light, ShadowRenderableList shadowRenderables, int flags) { // Edge groups should be 1:1 with shadow renderables Debug.Assert(edgeData.edgeGroups.Count == shadowRenderables.Count); LightType lightType = light.Type; bool extrudeToInfinity = (flags & (int)ShadowRenderableFlags.ExtrudeToInfinity) > 0; // Lock index buffer for writing IntPtr idxPtr = indexBuffer.Lock(BufferLocking.Discard); int indexStart = 0; unsafe { // TODO: Will currently cause an overflow for 32 bit indices, revisit short *pIdx = (short *)idxPtr.ToPointer(); int count = 0; // Iterate over the groups and form renderables for each based on their // lightFacing for (int groupCount = 0; groupCount < edgeData.edgeGroups.Count; groupCount++) { EdgeData.EdgeGroup eg = (EdgeData.EdgeGroup)edgeData.edgeGroups[groupCount]; ShadowRenderable si = (ShadowRenderable)shadowRenderables[groupCount]; RenderOperation lightShadOp = null; // Initialise the index bounds for this shadow renderable RenderOperation shadOp = si.GetRenderOperationForUpdate(); shadOp.indexData.indexCount = 0; shadOp.indexData.indexStart = indexStart; // original number of verts (without extruded copy) int originalVertexCount = eg.vertexData.vertexCount; bool firstDarkCapTri = true; int darkCapStart = 0; for (int edgeCount = 0; edgeCount < eg.edges.Count; edgeCount++) { EdgeData.Edge edge = (EdgeData.Edge)eg.edges[edgeCount]; EdgeData.Triangle t1 = (EdgeData.Triangle)edgeData.triangles[edge.triIndex[0]]; EdgeData.Triangle t2 = edge.isDegenerate ? (EdgeData.Triangle)edgeData.triangles[edge.triIndex[0]] : (EdgeData.Triangle)edgeData.triangles[edge.triIndex[1]]; if (t1.lightFacing && (edge.isDegenerate || !t2.lightFacing)) { /* Silhouette edge, first tri facing the light * Also covers degenerate tris where only tri 1 is valid * Remember verts run anticlockwise along the edge from * tri 0 so to point shadow volume tris outward, light cap * indexes have to be backwards * * We emit 2 tris if light is a point light, 1 if light * is directional, because directional lights cause all * points to converge to a single point at infinity. * * First side tri = near1, near0, far0 * Second tri = far0, far1, near1 * * 'far' indexes are 'near' index + originalVertexCount * because 'far' verts are in the second half of the * buffer */ pIdx[count++] = (short)edge.vertIndex[1]; pIdx[count++] = (short)edge.vertIndex[0]; pIdx[count++] = (short)(edge.vertIndex[0] + originalVertexCount); shadOp.indexData.indexCount += 3; if (!(lightType == LightType.Directional && extrudeToInfinity)) { // additional tri to make quad pIdx[count++] = (short)(edge.vertIndex[0] + originalVertexCount); pIdx[count++] = (short)(edge.vertIndex[1] + originalVertexCount); pIdx[count++] = (short)edge.vertIndex[1]; shadOp.indexData.indexCount += 3; } // Do dark cap tri // Use McGuire et al method, a triangle fan covering all silhouette // edges and one point (taken from the initial tri) if ((flags & (int)ShadowRenderableFlags.IncludeDarkCap) > 0) { if (firstDarkCapTri) { darkCapStart = edge.vertIndex[0] + originalVertexCount; firstDarkCapTri = false; } else { pIdx[count++] = (short)darkCapStart; pIdx[count++] = (short)(edge.vertIndex[1] + originalVertexCount); pIdx[count++] = (short)(edge.vertIndex[0] + originalVertexCount); shadOp.indexData.indexCount += 3; } } } else if (!t1.lightFacing && (edge.isDegenerate || t2.lightFacing)) { // Silhouette edge, second tri facing the light // Note edge indexes inverse of when t1 is light facing pIdx[count++] = (short)edge.vertIndex[0]; pIdx[count++] = (short)edge.vertIndex[1]; pIdx[count++] = (short)(edge.vertIndex[1] + originalVertexCount); shadOp.indexData.indexCount += 3; if (!(lightType == LightType.Directional && extrudeToInfinity)) { // additional tri to make quad pIdx[count++] = (short)(edge.vertIndex[1] + originalVertexCount); pIdx[count++] = (short)(edge.vertIndex[0] + originalVertexCount); pIdx[count++] = (short)edge.vertIndex[0]; shadOp.indexData.indexCount += 3; } // Do dark cap tri // Use McGuire et al method, a triangle fan covering all silhouette // edges and one point (taken from the initial tri) if ((flags & (int)ShadowRenderableFlags.IncludeDarkCap) > 0) { if (firstDarkCapTri) { darkCapStart = edge.vertIndex[1] + originalVertexCount; firstDarkCapTri = false; } else { pIdx[count++] = (short)darkCapStart; pIdx[count++] = (short)(edge.vertIndex[0] + originalVertexCount); pIdx[count++] = (short)(edge.vertIndex[1] + originalVertexCount); shadOp.indexData.indexCount += 3; } } } } // Do light cap if ((flags & (int)ShadowRenderableFlags.IncludeLightCap) > 0) { ShadowRenderable lightCapRend = null; if (si.IsLightCapSeperate) { // separate light cap lightCapRend = si.LightCapRenderable; lightShadOp = lightCapRend.GetRenderOperationForUpdate(); lightShadOp.indexData.indexCount = 0; // start indexes after the current total // NB we don't update the total here since that's done below lightShadOp.indexData.indexStart = indexStart + shadOp.indexData.indexCount; } for (int triCount = 0; triCount < edgeData.triangles.Count; triCount++) { EdgeData.Triangle t = (EdgeData.Triangle)edgeData.triangles[triCount]; // Light facing, and vertex set matches if (t.lightFacing && t.vertexSet == eg.vertexSet) { pIdx[count++] = (short)t.vertIndex[0]; pIdx[count++] = (short)t.vertIndex[1]; pIdx[count++] = (short)t.vertIndex[2]; if (lightShadOp != null) { lightShadOp.indexData.indexCount += 3; } else { shadOp.indexData.indexCount += 3; } } } } // update next indexStart (all renderables sharing the buffer) indexStart += shadOp.indexData.indexCount; // add on the light cap too if (lightShadOp != null) { indexStart += lightShadOp.indexData.indexCount; } } } // Unlock index buffer indexBuffer.Unlock(); Debug.Assert(indexStart <= indexBuffer.IndexCount, "Index buffer overrun while generating shadow volume!"); }
/// <summary> /// /// </summary> /// <param name="disposeManagedResources"></param> protected override void dispose( bool disposeManagedResources ) { if ( !this.IsDisposed ) { if ( disposeManagedResources ) { this.ClearScene(); this.RemoveAllCameras(); if ( op != null ) { if ( !op.IsDisposed ) op.Dispose(); op = null; } if ( this.autoParamDataSource != null ) { if ( !this.autoParamDataSource.IsDisposed ) this.autoParamDataSource.Dispose(); this.autoParamDataSource = null; } if ( this.rootSceneNode != null ) { if ( !this.rootSceneNode.IsDisposed ) this.rootSceneNode.Dispose(); this.rootSceneNode = null; } } } base.dispose( disposeManagedResources ); }
private void Init(int metersPerSample) { // set up the material normalMaterial = WorldManager.Instance.DefaultTerrainMaterial; material = normalMaterial; // create the render operation renderOp = new RenderOperation(); renderOp.operationType = OperationType.TriangleList; renderOp.useIndices = true; location = tile.Location; // ask the world manager what LOD we should use this.metersPerSample = metersPerSample; targetMetersPerSample = metersPerSample; // figure out the number of actual samples we need in the tile based on the size // and level of detail numSamples = tile.Size / metersPerSample; // allocate the storage for the height map heightMap = new float[numSamples * numSamples]; return; }