/// <summary> /// /// </summary> /// <param name="light"></param> /// <param name="extrusionDistance"></param> /// <returns></returns> public override AxisAlignedBox GetDarkCapBounds(Light light, float extrusionDistance) { // Extrude own light cap bounds // need a clone to avoid modifying the original bounding box worldDarkCapBounds = (AxisAlignedBox)GetLightCapBounds().Clone(); ExtrudeBounds(worldDarkCapBounds, light.GetAs4DVector(), extrusionDistance); return(worldDarkCapBounds); }
public IEnumerator GetShadowVolumeRenderableIterator(ShadowTechnique shadowTechnique, Light light, HardwareIndexBuffer indexBuffer, bool extrudeVertices, float extrusionDistance, ulong flags) { Debug.Assert(indexBuffer != null, "Only external index buffers are supported right now"); Debug.Assert(indexBuffer.Type == IndexType.Size16, "Only 16-bit indexes supported for now"); // Calculate the object space light details var lightPos = light.GetAs4DVector(); var world2Obj = parentNode.FullTransform.Inverse(); lightPos = world2Obj * lightPos; // We need to search the edge list for silhouette edges if (this.edgeList == null) { throw new Exception("You enabled stencil shadows after the buid process! In " + "Region.GetShadowVolumeRenderableIterator"); } // Init shadow renderable list if required var init = this.shadowRenderables.Count == 0; RegionShadowRenderable esr = null; //bool updatedSharedGeomNormals = false; for (var i = 0; i < this.edgeList.EdgeGroups.Count; i++) { var group = (EdgeData.EdgeGroup) this.edgeList.EdgeGroups[i]; if (init) { // Create a new renderable, create a separate light cap if // we're using a vertex program (either for this model, or // for extruding the shadow volume) since otherwise we can // get depth-fighting on the light cap esr = new RegionShadowRenderable(this, indexBuffer, group.vertexData, this.vertexProgramInUse || !extrudeVertices); this.shadowRenderables.Add(esr); } else { esr = (RegionShadowRenderable)this.shadowRenderables[i]; } // Extrude vertices in software if required if (extrudeVertices) { ExtrudeVertices(esr.PositionBuffer, group.vertexData.vertexCount, lightPos, extrusionDistance); } } return((IEnumerator)this.shadowRenderables); }
public override IEnumerator GetShadowVolumeRenderableEnumerator( ShadowTechnique technique, Light light, HardwareIndexBuffer indexBuffer, bool extrudeVertices, float extrusionDistance, int flags ) { Debug.Assert( indexBuffer != null, "Only external index buffers are supported right now" ); Debug.Assert( indexBuffer.Type == IndexType.Size16, "Only 16-bit indexes supported for now" ); // Potentially delegate to LOD entity if ( this.meshLodIndex > 0 && this.mesh.IsLodManual ) { Debug.Assert( this.meshLodIndex - 1 < this.lodEntityList.Count, "No LOD EntityList - did you build the manual LODs after creating the entity?" ); var lodEnt = this.lodEntityList[ this.meshLodIndex - 1 ]; // index - 1 as we skip index 0 (original LOD) if ( HasSkeleton && lodEnt.HasSkeleton ) { // Copy the animation state set to lod entity, we assume the lod // entity only has a subset animation states CopyAnimationStateSubset( lodEnt.animationState, this.animationState ); } return lodEnt.GetShadowVolumeRenderableEnumerator( technique, light, indexBuffer, extrudeVertices, extrusionDistance, flags ); } // Prep mesh if required // NB This seems to result in memory corruptions, having problems // tracking them down. For now, ensure that shadows are enabled // before any entities are created if ( !this.mesh.IsPreparedForShadowVolumes ) { this.mesh.PrepareForShadowVolume(); // reset frame last updated to force update of buffers this.frameAnimationLastUpdated = 0; // re-prepare buffers PrepareTempBlendedBuffers(); } // Update any animation UpdateAnimation(); // Calculate the object space light details var lightPos = light.GetAs4DVector(); // Only use object-space light if we're not doing transforms // Since when animating the positions are already transformed into // world space so we need world space light position var isAnimated = HasSkeleton || this.mesh.HasVertexAnimation; if ( !isAnimated ) { var world2Obj = parentNode.FullTransform.Inverse(); lightPos = world2Obj*lightPos; } // We need to search the edge list for silhouette edges var edgeList = GetEdgeList(); // Init shadow renderable list if required var init = ( this.shadowRenderables.Count == 0 ); if ( init ) { this.shadowRenderables.Capacity = edgeList.edgeGroups.Count; } var updatedSharedGeomNormals = false; EntityShadowRenderable esr = null; EdgeData.EdgeGroup egi; // note: using capacity for the loop since no items are in the list yet. // capacity is set to how large the collection will be in the end for ( var i = 0; i < this.shadowRenderables.Capacity; i++ ) { egi = (EdgeData.EdgeGroup)edgeList.edgeGroups[ i ]; var data = ( isAnimated ? FindBlendedVertexData( egi.vertexData ) : egi.vertexData ); if ( init ) { // Try to find corresponding SubEntity; this allows the // linkage of visibility between ShadowRenderable and SubEntity var subEntity = FindSubEntityForVertexData( egi.vertexData ); // Create a new renderable, create a separate light cap if // we're using hardware skinning since otherwise we get // depth-fighting on the light cap esr = new EntityShadowRenderable( this, indexBuffer, data, subEntity.VertexProgramInUse || !extrudeVertices, subEntity ); this.shadowRenderables.Add( esr ); } else { esr = (EntityShadowRenderable)this.shadowRenderables[ i ]; if ( HasSkeleton ) { // If we have a skeleton, we have no guarantee that the position // buffer we used last frame is the same one we used last frame // since a temporary buffer is requested each frame // therefore, we need to update the EntityShadowRenderable // with the current position buffer esr.RebindPositionBuffer( data, isAnimated ); } } // For animated entities we need to recalculate the face normals if ( isAnimated ) { if ( egi.vertexData != this.mesh.SharedVertexData || !updatedSharedGeomNormals ) { // recalculate face normals edgeList.UpdateFaceNormals( egi.vertexSet, esr.PositionBuffer ); // If we're not extruding in software we still need to update // the latter part of the buffer (the hardware extruded part) // with the latest animated positions if ( !extrudeVertices ) { var srcPtr = esr.PositionBuffer.Lock( BufferLocking.Normal ); var destPtr = srcPtr + ( egi.vertexData.vertexCount*12 ); // 12 = sizeof(float) * 3 Memory.Copy( srcPtr, destPtr, 12*egi.vertexData.vertexCount ); esr.PositionBuffer.Unlock(); } if ( egi.vertexData == this.mesh.SharedVertexData ) { updatedSharedGeomNormals = true; } } } // Extrude vertices in software if required if ( extrudeVertices ) { ExtrudeVertices( esr.PositionBuffer, egi.vertexData.vertexCount, lightPos, extrusionDistance ); } // Stop suppressing hardware update now, if we were esr.PositionBuffer.SuppressHardwareUpdate( false ); } // Calc triangle light facing UpdateEdgeListLightFacing( edgeList, lightPos ); // Generate indexes and update renderables GenerateShadowVolume( edgeList, indexBuffer, light, this.shadowRenderables, flags ); return this.shadowRenderables.GetEnumerator(); }
/// <summary> /// /// </summary> /// <param name="light"></param> /// <param name="extrusionDistance"></param> /// <returns></returns> public override AxisAlignedBox GetDarkCapBounds(Light light, float extrusionDistance) { // Extrude own light cap bounds // need a clone to avoid modifying the original bounding box worldDarkCapBounds = (AxisAlignedBox)GetLightCapBounds().Clone(); ExtrudeBounds(worldDarkCapBounds, light.GetAs4DVector(), extrusionDistance); return worldDarkCapBounds; }
/// <summary> /// /// </summary> /// <param name="lt"></param> /// <param name="lightindex"></param> private void SetGLLightPositionDirection( Light lt, All lightindex ) { // Set position / direction Vector4 vec = Vector4.Zero; // Use general 4D vector which is the same as GL's approach vec = lt.GetAs4DVector(); // Must convert to float* float[] tmp = new float[] { vec.x, vec.y, vec.z, vec.w }; OpenGL.Light( lightindex, All.Position, tmp ); // Set spotlight direction if ( lt.Type == LightType.Spotlight ) { Vector3 vec3 = lt.DerivedDirection; float[] tmp2 = new float[] { vec3.x, vec3.y, vec3.z, 0 }; OpenGL.Light( lightindex, All.SpotDirection, tmp2 ); } }
public IEnumerator GetShadowVolumeRenderableIterator( ShadowTechnique shadowTechnique, Light light, HardwareIndexBuffer indexBuffer, bool extrudeVertices, float extrusionDistance, ulong flags ) { Debug.Assert( indexBuffer != null, "Only external index buffers are supported right now" ); Debug.Assert( indexBuffer.Type == IndexType.Size16, "Only 16-bit indexes supported for now" ); // Calculate the object space light details var lightPos = light.GetAs4DVector(); var world2Obj = parentNode.FullTransform.Inverse(); lightPos = world2Obj*lightPos; // We need to search the edge list for silhouette edges if ( this.edgeList == null ) { throw new Exception( "You enabled stencil shadows after the buid process! In " + "Region.GetShadowVolumeRenderableIterator" ); } // Init shadow renderable list if required var init = this.shadowRenderables.Count == 0; RegionShadowRenderable esr = null; //bool updatedSharedGeomNormals = false; for ( var i = 0; i < this.edgeList.EdgeGroups.Count; i++ ) { var group = (EdgeData.EdgeGroup)this.edgeList.EdgeGroups[ i ]; if ( init ) { // Create a new renderable, create a separate light cap if // we're using a vertex program (either for this model, or // for extruding the shadow volume) since otherwise we can // get depth-fighting on the light cap esr = new RegionShadowRenderable( this, indexBuffer, group.vertexData, this.vertexProgramInUse || !extrudeVertices ); this.shadowRenderables.Add( esr ); } else { esr = (RegionShadowRenderable)this.shadowRenderables[ i ]; } // Extrude vertices in software if required if ( extrudeVertices ) { ExtrudeVertices( esr.PositionBuffer, group.vertexData.vertexCount, lightPos, extrusionDistance ); } } return (IEnumerator)this.shadowRenderables; }
private void SetGLLightPositionDirection( Light light, int index ) { // Use general 4D vector which is the same as GL's approach Vector4 vec4 = light.GetAs4DVector(); _tempLightVals[ 0 ] = vec4.x; _tempLightVals[ 1 ] = vec4.y; _tempLightVals[ 2 ] = vec4.z; _tempLightVals[ 3 ] = vec4.w; Gl.glLightfv( index, Gl.GL_POSITION, _tempLightVals ); // set spotlight direction if ( light.Type == LightType.Spotlight ) { var vec3 = light.DerivedDirection; _tempLightVals[ 0 ] = vec3.x; _tempLightVals[ 1 ] = vec3.y; _tempLightVals[ 2 ] = vec3.z; _tempLightVals[ 3 ] = 0.0f; Gl.glLightfv( index, Gl.GL_SPOT_DIRECTION, _tempLightVals ); } }
public override void ApplyDeltaValue(Vector4 val) { Vector4 v = light.GetAs4DVector(); SetValue(new Vector4(v.x + val.x, v.y + val.y, v.z + val.z, v.w + val.w)); }