2009-04-19 18:07:22 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* /
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
using System.Collections.Generic ;
using System.Drawing ;
using CodeImp.DoomBuilder.Data ;
2015-10-02 14:47:34 +00:00
using CodeImp.DoomBuilder.Geometry ;
2015-12-01 14:51:45 +00:00
using CodeImp.DoomBuilder.GZBuilder.Data ;
using CodeImp.DoomBuilder.GZBuilder.MD3 ;
2015-10-02 14:47:34 +00:00
using CodeImp.DoomBuilder.Map ;
using CodeImp.DoomBuilder.VisualModes ;
using SlimDX ;
using SlimDX.Direct3D9 ;
2018-02-03 20:31:34 +00:00
using CodeImp.DoomBuilder.GZBuilder ;
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
#endregion
namespace CodeImp.DoomBuilder.Rendering
{
internal sealed class Renderer3D : Renderer , IRenderer3D
{
#region = = = = = = = = = = = = = = = = = = Constants
private const float PROJ_NEAR_PLANE = 1f ;
private const float FOG_RANGE = 0.9f ;
2016-01-11 13:00:52 +00:00
private const int SHADERPASS_LIGHT = 17 ; //mxd
private const int SHADERPASS_SKYBOX = 5 ; //mxd
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// Matrices
private Matrix projection ;
private Matrix view3d ;
2015-10-02 14:47:34 +00:00
private Matrix viewproj ; //mxd
2009-04-19 18:07:22 +00:00
private Matrix billboard ;
private Matrix view2d ;
private Matrix world ;
private Vector3D cameraposition ;
2017-02-09 12:28:54 +00:00
private Vector3D cameravector ;
2009-04-19 18:07:22 +00:00
private int shaderpass ;
// Window size
private Size windowsize ;
// Frustum
private ProjectedFrustum2D frustum ;
// Thing cage
2013-09-11 09:47:53 +00:00
private bool renderthingcages ;
//mxd
2016-01-14 22:15:54 +00:00
private VisualVertexHandle vertexhandle ;
2013-09-11 09:47:53 +00:00
private int [ ] lightOffsets ;
2009-04-19 18:07:22 +00:00
// Crosshair
private FlatVertex [ ] crosshairverts ;
private bool crosshairbusy ;
// Highlighting
private IVisualPickable highlighted ;
private float highlightglow ;
2009-05-05 21:13:50 +00:00
private float highlightglowinv ;
2009-07-07 14:52:39 +00:00
private bool showselection ;
private bool showhighlight ;
2009-04-19 18:07:22 +00:00
2015-09-27 21:09:14 +00:00
//mxd. Solid geometry to be rendered. Must be sorted by sector.
private Dictionary < ImageData , List < VisualGeometry > > solidgeo ;
2009-04-19 18:07:22 +00:00
2015-09-27 21:09:14 +00:00
//mxd. Masked geometry to be rendered. Must be sorted by sector.
private Dictionary < ImageData , List < VisualGeometry > > maskedgeo ;
2009-04-19 18:07:22 +00:00
2015-12-01 14:51:45 +00:00
//mxd. Translucent geometry to be rendered. Must be sorted by camera distance.
2015-09-27 21:09:14 +00:00
private List < VisualGeometry > translucentgeo ;
2016-01-11 13:00:52 +00:00
//mxd. Geometry to be rendered as skybox.
private List < VisualGeometry > skygeo ;
2015-09-27 21:09:14 +00:00
//mxd. Solid things to be rendered (currently(?) there won't be any). Must be sorted by sector.
private Dictionary < ImageData , List < VisualThing > > solidthings ;
//mxd. Masked things to be rendered. Must be sorted by sector.
private Dictionary < ImageData , List < VisualThing > > maskedthings ;
//mxd. Translucent things to be rendered. Must be sorted by camera distance.
private List < VisualThing > translucentthings ;
2015-12-01 14:51:45 +00:00
//mxd. Things with attached dynamic lights
private List < VisualThing > lightthings ;
//mxd. Things, which should be rendered as models
private Dictionary < ModelData , List < VisualThing > > maskedmodelthings ;
//mxd. Things, which should be rendered as translucent models
private List < VisualThing > translucentmodelthings ;
2015-09-27 21:09:14 +00:00
//mxd. All things. Used to render thing cages
private List < VisualThing > allthings ;
2013-03-18 13:52:27 +00:00
//mxd. Visual vertices
2015-10-02 14:47:34 +00:00
private List < VisualVertex > visualvertices ;
//mxd. Event lines
private List < Line3D > eventlines ;
2013-09-11 09:47:53 +00:00
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
public ProjectedFrustum2D Frustum2D { get { return frustum ; } }
public bool DrawThingCages { get { return renderthingcages ; } set { renderthingcages = value ; } }
2009-07-07 14:52:39 +00:00
public bool ShowSelection { get { return showselection ; } set { showselection = value ; } }
public bool ShowHighlight { get { return showhighlight ; } set { showhighlight = value ; } }
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
internal Renderer3D ( D3DDevice graphics ) : base ( graphics )
{
// Initialize
2017-08-27 05:09:28 +00:00
//CreateProjection(); // [ZZ] don't do undefined things once not even ready
2009-04-19 18:07:22 +00:00
CreateMatrices2D ( ) ;
renderthingcages = true ;
2009-07-07 14:52:39 +00:00
showselection = true ;
showhighlight = true ;
2015-10-02 14:47:34 +00:00
eventlines = new List < Line3D > ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Dummy frustum
frustum = new ProjectedFrustum2D ( new Vector2D ( ) , 0.0f , 0.0f , PROJ_NEAR_PLANE ,
2014-02-21 14:42:12 +00:00
General . Settings . ViewDistance , Angle2D . DegToRad ( General . Settings . VisualFOV ) ) ;
2009-04-19 18:07:22 +00:00
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
// Disposer
2016-02-01 22:04:00 +00:00
public override void Dispose ( )
2009-04-19 18:07:22 +00:00
{
// Not already disposed?
if ( ! isdisposed )
{
// Clean up
2016-01-14 22:15:54 +00:00
if ( vertexhandle ! = null ) vertexhandle . Dispose ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Done
base . Dispose ( ) ;
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Management
// This is called before a device is reset
// (when resized or display adapter was changed)
public override void UnloadResource ( )
{
crosshairverts = null ;
}
// This is called resets when the device is reset
// (when resized or display adapter was changed)
public override void ReloadResource ( )
{
CreateMatrices2D ( ) ;
}
// This makes screen vertices for display
private void CreateCrosshairVerts ( Size texturesize )
{
// Determine coordinates
2014-02-21 14:42:12 +00:00
float width = windowsize . Width ;
float height = windowsize . Height ;
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
RectangleF rect = new RectangleF ( ( float ) Math . Round ( ( width - texturesize . Width ) * 0.5f ) , ( float ) Math . Round ( ( height - texturesize . Height ) * 0.5f ) , texturesize . Width , texturesize . Height ) ;
2009-04-19 18:07:22 +00:00
// Make vertices
crosshairverts = new FlatVertex [ 4 ] ;
crosshairverts [ 0 ] . x = rect . Left ;
crosshairverts [ 0 ] . y = rect . Top ;
crosshairverts [ 0 ] . c = - 1 ;
crosshairverts [ 1 ] . x = rect . Right ;
crosshairverts [ 1 ] . y = rect . Top ;
crosshairverts [ 1 ] . c = - 1 ;
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
crosshairverts [ 1 ] . u = 1.0f ;
2009-04-19 18:07:22 +00:00
crosshairverts [ 2 ] . x = rect . Left ;
crosshairverts [ 2 ] . y = rect . Bottom ;
crosshairverts [ 2 ] . c = - 1 ;
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
crosshairverts [ 2 ] . v = 1.0f ;
2009-04-19 18:07:22 +00:00
crosshairverts [ 3 ] . x = rect . Right ;
crosshairverts [ 3 ] . y = rect . Bottom ;
crosshairverts [ 3 ] . c = - 1 ;
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
crosshairverts [ 3 ] . u = 1.0f ;
crosshairverts [ 3 ] . v = 1.0f ;
2009-04-19 18:07:22 +00:00
}
#endregion
2009-05-04 06:13:56 +00:00
#region = = = = = = = = = = = = = = = = = = Resources
2009-04-19 18:07:22 +00:00
2014-09-16 08:51:27 +00:00
//mxd
internal void UpdateVertexHandle ( )
{
2016-01-14 22:15:54 +00:00
if ( vertexhandle ! = null )
{
vertexhandle . UnloadResource ( ) ;
vertexhandle . ReloadResource ( ) ;
}
2013-09-11 09:47:53 +00:00
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Presentation
// This creates the projection
internal void CreateProjection ( )
{
// Calculate aspect
2017-08-27 05:09:28 +00:00
float screenheight = General . Map . Graphics . RenderTarget . ClientSize . Height * ( General . Settings . GZStretchView ? General . Map . Data . InvertedVerticalViewStretch : 1.0f ) ; //mxd
2014-09-20 18:34:06 +00:00
float aspect = General . Map . Graphics . RenderTarget . ClientSize . Width / screenheight ;
2009-04-19 18:07:22 +00:00
// The DirectX PerspectiveFovRH matrix method calculates the scaling in X and Y as follows:
// yscale = 1 / tan(fovY / 2)
// xscale = yscale / aspect
// The fov specified in the method is the FOV over Y, but we want the user to specify the FOV
// over X, so calculate what it would be over Y first;
2014-02-21 14:42:12 +00:00
float fov = Angle2D . DegToRad ( General . Settings . VisualFOV ) ;
2009-04-19 18:07:22 +00:00
float reversefov = 1.0f / ( float ) Math . Tan ( fov / 2.0f ) ;
float reversefovy = reversefov * aspect ;
float fovy = ( float ) Math . Atan ( 1.0f / reversefovy ) * 2.0f ;
// Make the projection matrix
projection = Matrix . PerspectiveFovRH ( fovy , aspect , PROJ_NEAR_PLANE , General . Settings . ViewDistance ) ;
2016-01-14 22:15:54 +00:00
viewproj = view3d * projection ; //mxd
2009-04-19 18:07:22 +00:00
}
// This creates matrices for a camera view
public void PositionAndLookAt ( Vector3D pos , Vector3D lookat )
{
// Calculate delta vector
cameraposition = pos ;
2017-02-09 12:28:54 +00:00
Vector3D delta = lookat - pos ;
cameravector = delta . GetNormal ( ) ;
float anglexy = delta . GetAngleXY ( ) ;
2014-02-21 14:42:12 +00:00
float anglez = delta . GetAngleZ ( ) ;
2009-04-19 18:07:22 +00:00
// Create frustum
frustum = new ProjectedFrustum2D ( pos , anglexy , anglez , PROJ_NEAR_PLANE ,
2013-08-08 11:04:13 +00:00
General . Settings . ViewDistance , Angle2D . DegToRad ( General . Settings . VisualFOV ) ) ;
2009-04-19 18:07:22 +00:00
// Make the view matrix
view3d = Matrix . LookAtRH ( D3DDevice . V3 ( pos ) , D3DDevice . V3 ( lookat ) , new Vector3 ( 0f , 0f , 1f ) ) ;
2015-10-02 14:47:34 +00:00
viewproj = view3d * projection ; //mxd
2009-04-19 18:07:22 +00:00
// Make the billboard matrix
billboard = Matrix . RotationZ ( anglexy + Angle2D . PI ) ;
}
// This creates 2D view matrix
private void CreateMatrices2D ( )
{
windowsize = graphics . RenderTarget . ClientSize ;
2014-02-21 14:42:12 +00:00
Matrix scaling = Matrix . Scaling ( ( 1f / windowsize . Width ) * 2f , ( 1f / windowsize . Height ) * - 2f , 1f ) ;
2009-04-19 18:07:22 +00:00
Matrix translate = Matrix . Translation ( - ( float ) windowsize . Width * 0.5f , - ( float ) windowsize . Height * 0.5f , 0f ) ;
2015-10-02 14:47:34 +00:00
view2d = translate * scaling ;
2009-04-19 18:07:22 +00:00
}
// This applies the matrices
private void ApplyMatrices3D ( )
{
2015-10-02 14:47:34 +00:00
graphics . Shaders . World3D . WorldViewProj = world * viewproj ; //mxd. Multiplication is ~2x faster than "world * view3d * projection";
2009-04-19 18:07:22 +00:00
}
// This sets the appropriate view matrix
public void ApplyMatrices2D ( )
{
graphics . Device . SetTransform ( TransformState . World , world ) ;
graphics . Device . SetTransform ( TransformState . Projection , Matrix . Identity ) ;
graphics . Device . SetTransform ( TransformState . View , view2d ) ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Start / Finish
// This starts rendering
public bool Start ( )
{
// Start drawing
if ( graphics . StartRendering ( true , General . Colors . Background . ToColorValue ( ) , graphics . BackBuffer , graphics . DepthBuffer ) )
{
2013-09-11 09:47:53 +00:00
// Beginning renderstates
2009-04-19 18:07:22 +00:00
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . InverseSourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . FogDensity , 1.0f ) ;
graphics . Device . SetRenderState ( RenderState . FogColor , General . Colors . Background . ToInt ( ) ) ;
graphics . Device . SetRenderState ( RenderState . FogStart , General . Settings . ViewDistance * FOG_RANGE ) ;
graphics . Device . SetRenderState ( RenderState . FogEnd , General . Settings . ViewDistance ) ;
graphics . Device . SetRenderState ( RenderState . FogTableMode , FogMode . Linear ) ;
graphics . Device . SetRenderState ( RenderState . RangeFogEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
2015-10-02 14:47:34 +00:00
graphics . Shaders . World3D . HighlightColor = new Color4 ( ) ; //mxd
2009-04-19 18:07:22 +00:00
2009-04-26 20:20:40 +00:00
// Texture addressing
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressU , TextureAddress . Wrap ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressV , TextureAddress . Wrap ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressW , TextureAddress . Wrap ) ;
2009-04-19 18:07:22 +00:00
// Matrices
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
// Highlight
2009-05-04 06:13:56 +00:00
if ( General . Settings . AnimateVisualSelection )
{
2016-08-29 10:06:16 +00:00
highlightglow = ( float ) Math . Sin ( Clock . CurrentTime / 100.0f ) * 0.1f + 0.4f ;
2013-09-11 09:47:53 +00:00
highlightglowinv = - highlightglow + 0.8f ;
2009-05-04 06:13:56 +00:00
}
else
{
2009-05-06 07:26:12 +00:00
highlightglow = 0.4f ;
highlightglowinv = 0.3f ;
2009-05-04 06:13:56 +00:00
}
2009-04-19 18:07:22 +00:00
// Determine shader pass to use
2015-09-25 13:20:53 +00:00
shaderpass = ( fullbrightness ? 1 : 0 ) ;
2009-04-19 18:07:22 +00:00
// Create crosshair vertices
if ( crosshairverts = = null )
CreateCrosshairVerts ( new Size ( General . Map . Data . Crosshair3D . Width , General . Map . Data . Crosshair3D . Height ) ) ;
2016-01-14 22:15:54 +00:00
//mxd. Crate vertex handle
if ( vertexhandle = = null ) vertexhandle = new VisualVertexHandle ( ) ;
2009-04-19 18:07:22 +00:00
// Ready
return true ;
}
else
{
// Can't render now
return false ;
}
}
// This begins rendering world geometry
public void StartGeometry ( )
{
2015-09-27 21:09:14 +00:00
// Make collections
solidgeo = new Dictionary < ImageData , List < VisualGeometry > > ( ) ; //mxd
maskedgeo = new Dictionary < ImageData , List < VisualGeometry > > ( ) ; //mxd
translucentgeo = new List < VisualGeometry > ( ) ; //mxd
2016-01-11 13:00:52 +00:00
skygeo = new List < VisualGeometry > ( ) ; //mxd
2015-09-27 21:09:14 +00:00
solidthings = new Dictionary < ImageData , List < VisualThing > > ( ) ; //mxd
maskedthings = new Dictionary < ImageData , List < VisualThing > > ( ) ; //mxd
translucentthings = new List < VisualThing > ( ) ; //mxd
2015-12-01 14:51:45 +00:00
maskedmodelthings = new Dictionary < ModelData , List < VisualThing > > ( ) ; //mxd
translucentmodelthings = new List < VisualThing > ( ) ; //mxd
2015-09-27 21:09:14 +00:00
lightthings = new List < VisualThing > ( ) ; //mxd
allthings = new List < VisualThing > ( ) ; //mxd
2009-04-19 18:07:22 +00:00
}
// This ends rendering world geometry
public void FinishGeometry ( )
{
2015-09-27 21:09:14 +00:00
//mxd. Sort lights
if ( General . Settings . GZDrawLightsMode ! = LightRenderMode . NONE & & ! fullbrightness & & lightthings . Count > 0 )
2014-12-03 23:15:26 +00:00
UpdateLights ( ) ;
2017-04-29 10:56:06 +00:00
2013-09-11 09:47:53 +00:00
// Initial renderstates
2009-04-19 18:07:22 +00:00
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . Counterclockwise ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Shaders . World3D . Begin ( ) ;
2016-01-11 13:00:52 +00:00
//mxd. SKY PASS
if ( skygeo . Count > 0 )
{
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
RenderSky ( skygeo ) ;
}
2009-04-19 18:07:22 +00:00
// SOLID PASS
2012-08-10 12:08:08 +00:00
world = Matrix . Identity ;
2009-04-19 18:07:22 +00:00
ApplyMatrices3D ( ) ;
2017-04-29 10:56:06 +00:00
RenderSinglePass ( solidgeo , solidthings ) ;
2009-04-19 18:07:22 +00:00
2015-12-01 14:51:45 +00:00
//mxd. Render models, without backface culling
if ( maskedmodelthings . Count > 0 )
{
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
2017-07-26 15:35:22 +00:00
RenderModels ( false , false ) ;
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . Counterclockwise ) ;
2015-12-01 14:51:45 +00:00
}
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
// MASK PASS
2015-12-01 14:51:45 +00:00
if ( maskedgeo . Count > 0 | | maskedthings . Count > 0 )
{
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , true ) ;
RenderSinglePass ( maskedgeo , maskedthings ) ;
}
2013-09-11 09:47:53 +00:00
2015-09-27 21:09:14 +00:00
//mxd. LIGHT PASS
if ( General . Settings . GZDrawLightsMode ! = LightRenderMode . NONE & & ! fullbrightness & & lightthings . Count > 0 )
{
2015-12-01 14:51:45 +00:00
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . One ) ;
2015-09-27 21:09:14 +00:00
RenderLights ( solidgeo , lightthings ) ;
RenderLights ( maskedgeo , lightthings ) ;
2017-07-26 15:35:22 +00:00
if ( maskedmodelthings . Count > 0 )
{
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Shaders . World3D . IgnoreNormals = true ;
RenderModels ( true , false ) ;
graphics . Shaders . World3D . IgnoreNormals = false ;
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . Counterclockwise ) ;
}
}
2015-09-27 21:09:14 +00:00
// ALPHA AND ADDITIVE PASS
2015-12-01 14:51:45 +00:00
if ( translucentgeo . Count > 0 | | translucentthings . Count > 0 )
{
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
RenderTranslucentPass ( translucentgeo , translucentthings ) ;
}
2017-02-09 13:03:22 +00:00
// [ZZ] LIGHT PASS on ALPHA GEOMETRY (GZDoom does this)
if ( General . Settings . GZDrawLightsMode ! = LightRenderMode . NONE & & ! fullbrightness & & lightthings . Count > 0 & & translucentgeo . Count > 0 )
{
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . One ) ;
RenderTranslucentLights ( translucentgeo , lightthings ) ;
}
2015-12-01 14:51:45 +00:00
//mxd. Render translucent models, with backface culling
if ( translucentmodelthings . Count > 0 )
{
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
2017-07-26 15:35:22 +00:00
RenderModels ( false , true ) ;
}
2013-09-11 09:47:53 +00:00
2017-07-26 15:35:22 +00:00
// [ZZ] light pass on alpha models
if ( General . Settings . GZDrawLightsMode ! = LightRenderMode . NONE & & ! fullbrightness & & lightthings . Count > 0 & & translucentmodelthings . Count > 0 )
{
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , true ) ;
graphics . Shaders . World3D . IgnoreNormals = true ;
2017-07-26 16:34:01 +00:00
RenderModels ( true , true ) ;
2017-07-26 15:35:22 +00:00
graphics . Shaders . World3D . IgnoreNormals = false ;
}
// THING CAGES
if ( renderthingcages )
2015-12-01 14:51:45 +00:00
{
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
RenderThingCages ( ) ;
}
2009-04-19 18:07:22 +00:00
2013-03-18 13:52:27 +00:00
//mxd. Visual vertices
RenderVertices ( ) ;
2015-08-08 21:56:43 +00:00
//mxd. Event lines
2015-10-02 14:47:34 +00:00
if ( General . Settings . GZShowEventLines ) RenderArrows ( eventlines ) ;
2009-04-19 18:07:22 +00:00
// Remove references
graphics . Shaders . World3D . Texture1 = null ;
// Done
graphics . Shaders . World3D . End ( ) ;
2015-09-27 21:09:14 +00:00
//mxd. Trash collections
solidgeo = null ;
maskedgeo = null ;
translucentgeo = null ;
2016-01-11 13:00:52 +00:00
skygeo = null ;
2015-09-27 21:09:14 +00:00
solidthings = null ;
maskedthings = null ;
translucentthings = null ;
allthings = null ;
lightthings = null ;
2015-12-01 14:51:45 +00:00
maskedmodelthings = null ;
translucentmodelthings = null ;
2015-09-27 21:09:14 +00:00
visualvertices = null ;
2009-04-19 18:07:22 +00:00
}
2017-02-09 12:28:54 +00:00
// [ZZ] black renderer magic here.
// todo maybe implement proper frustum culling eventually?
// Frustum2D.IntersectCircle doesn't seem to work here.
private bool CullLight ( VisualThing t )
{
Vector3D lightToCamera = ( cameraposition - t . CenterV3D ) . GetNormal ( ) ;
double angdiff = Vector3D . DotProduct ( lightToCamera , cameravector ) ;
if ( angdiff < = 0 )
return true ; // light in front of the camera. it's not negative because I don't want to calculate things twice and need the vector to point at camera.
// otherwise check light size: large lights might have center on the back, but radius in front of the camera.
Vector3D lightToCameraWithRadius = ( cameraposition - ( t . CenterV3D + lightToCamera * t . LightRadius ) ) . GetNormal ( ) ;
double angdiffWithRadius = Vector3D . DotProduct ( lightToCameraWithRadius , cameravector ) ;
if ( angdiffWithRadius < = 0 )
return true ; // light's radius extension is in front of the camera.
return false ;
}
//mxd
private void UpdateLights ( )
2014-12-03 23:15:26 +00:00
{
2017-02-09 12:28:54 +00:00
// Calculate distance to camera
foreach ( VisualThing t in lightthings ) t . CalculateCameraDistance ( cameraposition ) ;
// Sort by it, closer ones first
lightthings . Sort ( ( t1 , t2 ) = > Math . Sign ( t1 . CameraDistance - t2 . CameraDistance ) ) ;
// Gather the closest
List < VisualThing > tl = new List < VisualThing > ( lightthings . Count ) ;
// Break on either end of things of max dynamic lights reached
for ( int i = 0 ; i < lightthings . Count & & tl . Count < General . Settings . GZMaxDynamicLights ; i + + )
{
// Make sure we can see this light at all
if ( ! CullLight ( lightthings [ i ] ) )
continue ;
tl . Add ( lightthings [ i ] ) ;
}
// Update the array
lightthings = tl ;
2013-09-11 09:47:53 +00:00
2015-09-27 21:09:14 +00:00
// Sort things by light render style
2018-02-03 20:31:34 +00:00
lightthings . Sort ( ( t1 , t2 ) = > Math . Sign ( t1 . LightType . LightRenderStyle - t2 . LightType . LightRenderStyle ) ) ;
2017-01-19 22:17:43 +00:00
lightOffsets = new int [ 4 ] ;
2015-09-27 21:09:14 +00:00
foreach ( VisualThing t in lightthings )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
//add light to apropriate array.
2018-02-03 20:31:34 +00:00
switch ( t . LightType . LightRenderStyle )
2014-12-03 23:15:26 +00:00
{
2018-02-03 20:31:34 +00:00
case GZGeneral . LightRenderStyle . NORMAL :
case GZGeneral . LightRenderStyle . VAVOOM : lightOffsets [ 0 ] + + ; break ;
case GZGeneral . LightRenderStyle . ADDITIVE : lightOffsets [ 2 ] + + ; break ;
case GZGeneral . LightRenderStyle . SUBTRACTIVE : lightOffsets [ 3 ] + + ; break ;
2017-02-09 11:28:55 +00:00
default : lightOffsets [ 1 ] + + ; break ; // attenuated
2013-12-23 08:00:19 +00:00
}
2013-09-11 09:47:53 +00:00
}
}
//mxd.
//I never particularly liked old ThingCages, so I wrote this instead.
//It should render faster and it has fancy arrow! :)
2014-12-03 23:15:26 +00:00
private void RenderThingCages ( )
{
2013-09-11 09:47:53 +00:00
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . SourceAlpha ) ;
graphics . Shaders . World3D . BeginPass ( 16 ) ;
2015-09-27 21:09:14 +00:00
foreach ( VisualThing t in allthings )
2014-12-03 23:15:26 +00:00
{
2013-09-11 09:47:53 +00:00
// Setup color
2015-09-27 21:09:14 +00:00
Color4 thingcolor ;
if ( t . Selected & & showselection )
2014-12-03 23:15:26 +00:00
{
2015-09-27 21:09:14 +00:00
thingcolor = General . Colors . Selection3D . ToColorValue ( ) ;
2014-12-03 23:15:26 +00:00
}
2015-09-27 21:09:14 +00:00
else
2014-12-03 23:15:26 +00:00
{
2015-09-27 21:09:14 +00:00
thingcolor = t . CageColor ;
if ( t ! = highlighted ) thingcolor . Alpha = 0.6f ;
2013-09-11 09:47:53 +00:00
}
2015-09-27 21:09:14 +00:00
graphics . Shaders . World3D . VertexColor = thingcolor ;
2013-09-11 09:47:53 +00:00
//Render cage
graphics . Shaders . World3D . ApplySettings ( ) ;
2015-10-02 14:47:34 +00:00
graphics . Device . SetStreamSource ( 0 , t . CageBuffer , 0 , WorldVertex . Stride ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . LineList , 0 , t . CageLength ) ;
2013-09-11 09:47:53 +00:00
}
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
// Done
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
}
2012-09-17 15:41:18 +00:00
2013-03-18 13:52:27 +00:00
//mxd
2014-12-03 23:15:26 +00:00
private void RenderVertices ( )
{
2013-03-18 13:52:27 +00:00
if ( visualvertices = = null ) return ;
2013-03-20 10:25:32 +00:00
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . SourceAlpha ) ;
2013-03-18 13:52:27 +00:00
graphics . Shaders . World3D . BeginPass ( 16 ) ;
2014-12-03 23:15:26 +00:00
foreach ( VisualVertex v in visualvertices )
{
2013-03-18 13:52:27 +00:00
world = v . Position ;
ApplyMatrices3D ( ) ;
// Setup color
2014-02-21 14:42:12 +00:00
Color4 color ;
2014-12-03 23:15:26 +00:00
if ( v . Selected & & showselection )
{
2013-03-18 13:52:27 +00:00
color = General . Colors . Selection3D . ToColorValue ( ) ;
2014-12-03 23:15:26 +00:00
}
else
{
2013-05-02 11:03:16 +00:00
color = v . HaveHeightOffset ? General . Colors . InfoLine . ToColorValue ( ) : General . Colors . Vertices . ToColorValue ( ) ;
2013-03-18 13:52:27 +00:00
if ( v ! = highlighted ) color . Alpha = 0.6f ;
}
graphics . Shaders . World3D . VertexColor = color ;
//Commence drawing!!11
graphics . Shaders . World3D . ApplySettings ( ) ;
2016-01-14 22:15:54 +00:00
graphics . Device . SetStreamSource ( 0 , v . CeilingVertex ? vertexhandle . Upper : vertexhandle . Lower , 0 , WorldVertex . Stride ) ;
2013-03-21 11:23:29 +00:00
graphics . Device . DrawPrimitives ( PrimitiveType . LineList , 0 , 8 ) ;
2013-03-18 13:52:27 +00:00
}
// Done
graphics . Shaders . World3D . EndPass ( ) ;
2013-03-20 10:25:32 +00:00
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
2013-03-18 13:52:27 +00:00
}
2013-09-11 09:47:53 +00:00
//mxd
2015-08-08 21:56:43 +00:00
private void RenderArrows ( ICollection < Line3D > lines )
2014-12-03 23:15:26 +00:00
{
2015-08-08 21:56:43 +00:00
// Calculate required points count
if ( lines . Count = = 0 ) return ;
int pointscount = 0 ;
2015-12-14 12:34:31 +00:00
foreach ( Line3D line in lines ) pointscount + = ( line . RenderArrowhead ? 6 : 2 ) ; // 4 extra points for the arrowhead
2015-08-08 21:56:43 +00:00
if ( pointscount < 2 ) return ;
2013-09-11 09:47:53 +00:00
//create vertices
2015-08-08 21:56:43 +00:00
WorldVertex [ ] verts = new WorldVertex [ pointscount ] ;
2014-12-03 23:15:26 +00:00
const float scaler = 20f ;
2015-08-08 21:56:43 +00:00
pointscount = 0 ;
foreach ( Line3D line in lines )
2014-12-03 23:15:26 +00:00
{
2015-12-28 15:01:53 +00:00
int color = line . Color . ToInt ( ) ;
2015-08-08 21:56:43 +00:00
// Add regular points
2015-12-14 12:34:31 +00:00
verts [ pointscount ] . x = line . Start . x ;
verts [ pointscount ] . y = line . Start . y ;
verts [ pointscount ] . z = line . Start . z ;
2015-08-08 21:56:43 +00:00
verts [ pointscount ] . c = color ;
pointscount + + ;
2015-12-14 12:34:31 +00:00
verts [ pointscount ] . x = line . End . x ;
verts [ pointscount ] . y = line . End . y ;
verts [ pointscount ] . z = line . End . z ;
2015-08-08 21:56:43 +00:00
verts [ pointscount ] . c = color ;
pointscount + + ;
// Add arrowhead
2015-12-14 12:34:31 +00:00
if ( line . RenderArrowhead )
2015-08-08 21:56:43 +00:00
{
float nz = line . GetDelta ( ) . GetNormal ( ) . z * scaler ;
float angle = line . GetAngle ( ) ;
2015-12-14 12:34:31 +00:00
Vector3D a1 = new Vector3D ( line . End . x - scaler * ( float ) Math . Sin ( angle - 0.46f ) , line . End . y + scaler * ( float ) Math . Cos ( angle - 0.46f ) , line . End . z - nz ) ;
Vector3D a2 = new Vector3D ( line . End . x - scaler * ( float ) Math . Sin ( angle + 0.46f ) , line . End . y + scaler * ( float ) Math . Cos ( angle + 0.46f ) , line . End . z - nz ) ;
2015-08-08 21:56:43 +00:00
verts [ pointscount ] = verts [ pointscount - 1 ] ;
verts [ pointscount + 1 ] . x = a1 . x ;
verts [ pointscount + 1 ] . y = a1 . y ;
verts [ pointscount + 1 ] . z = a1 . z ;
verts [ pointscount + 1 ] . c = color ;
verts [ pointscount + 2 ] = verts [ pointscount - 1 ] ;
verts [ pointscount + 3 ] . x = a2 . x ;
verts [ pointscount + 3 ] . y = a2 . y ;
verts [ pointscount + 3 ] . z = a2 . z ;
verts [ pointscount + 3 ] . c = color ;
pointscount + = 4 ;
}
2013-09-11 09:47:53 +00:00
}
VertexBuffer vb = new VertexBuffer ( General . Map . Graphics . Device , WorldVertex . Stride * verts . Length , Usage . WriteOnly | Usage . Dynamic , VertexFormat . None , Pool . Default ) ;
DataStream s = vb . Lock ( 0 , WorldVertex . Stride * verts . Length , LockFlags . Discard ) ;
2014-12-03 23:15:26 +00:00
s . WriteRange ( verts ) ;
2013-09-11 09:47:53 +00:00
vb . Unlock ( ) ;
s . Dispose ( ) ;
//begin rendering
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . SourceAlpha ) ;
2015-08-08 21:56:43 +00:00
graphics . Shaders . World3D . BeginPass ( 15 ) ;
2013-09-11 09:47:53 +00:00
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
//render
graphics . Shaders . World3D . ApplySettings ( ) ;
graphics . Device . SetStreamSource ( 0 , vb , 0 , WorldVertex . Stride ) ;
2015-08-08 21:56:43 +00:00
graphics . Device . DrawPrimitives ( PrimitiveType . LineList , 0 , pointscount / 2 ) ;
2012-09-17 15:41:18 +00:00
2013-09-11 09:47:53 +00:00
// Done
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
2012-09-17 21:57:08 +00:00
vb . Dispose ( ) ;
2013-09-11 09:47:53 +00:00
}
2009-04-19 18:07:22 +00:00
// This performs a single render pass
2015-09-27 21:09:14 +00:00
private void RenderSinglePass ( Dictionary < ImageData , List < VisualGeometry > > geopass , Dictionary < ImageData , List < VisualThing > > thingspass )
2009-04-19 18:07:22 +00:00
{
2015-10-02 14:47:34 +00:00
ImageData curtexture ;
2013-09-11 09:47:53 +00:00
int currentshaderpass = shaderpass ;
2009-05-01 20:31:17 +00:00
int highshaderpass = shaderpass + 2 ;
2009-04-19 18:07:22 +00:00
// Begin rendering with this shader
graphics . Shaders . World3D . BeginPass ( shaderpass ) ;
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
// Render the geometry collected
2015-09-27 21:09:14 +00:00
foreach ( KeyValuePair < ImageData , List < VisualGeometry > > group in geopass )
2009-04-19 18:07:22 +00:00
{
// What texture to use?
if ( group . Key is UnknownImage )
curtexture = General . Map . Data . UnknownTexture3D ;
2015-09-27 21:09:14 +00:00
else if ( group . Key . IsImageLoaded & & ! group . Key . IsDisposed )
2009-04-19 18:07:22 +00:00
curtexture = group . Key ;
else
curtexture = General . Map . Data . Hourglass3D ;
// Create Direct3D texture if still needed
if ( ( curtexture . Texture = = null ) | | curtexture . Texture . Disposed )
curtexture . CreateTexture ( ) ;
// Apply texture
graphics . Shaders . World3D . Texture1 = curtexture . Texture ;
2015-09-27 21:09:14 +00:00
//mxd. Sort geometry by sector index
group . Value . Sort ( ( g1 , g2 ) = > g1 . Sector . Sector . FixedIndex - g2 . Sector . Sector . FixedIndex ) ;
2009-04-19 18:07:22 +00:00
// Go for all geometry that uses this texture
VisualSector sector = null ;
2013-09-11 09:47:53 +00:00
2009-04-19 18:07:22 +00:00
foreach ( VisualGeometry g in group . Value )
{
// Changing sector?
if ( ! object . ReferenceEquals ( g . Sector , sector ) )
{
// Update the sector if needed
if ( g . Sector . NeedsUpdateGeo ) g . Sector . Update ( ) ;
// Only do this sector when a vertexbuffer is created
2015-10-02 14:47:34 +00:00
//mxd. No Map means that sector was deleted recently, I suppose
2015-12-28 15:01:53 +00:00
if ( g . Sector . GeometryBuffer ! = null & & g . Sector . Sector . Map ! = null )
2009-04-19 18:07:22 +00:00
{
// Change current sector
sector = g . Sector ;
// Set stream source
graphics . Device . SetStreamSource ( 0 , sector . GeometryBuffer , 0 , WorldVertex . Stride ) ;
}
else
{
sector = null ;
}
2012-06-03 15:13:22 +00:00
}
2018-04-10 16:41:35 +00:00
graphics . Shaders . World3D . Desaturation = 0 ;
if ( sector ! = null )
2009-04-19 18:07:22 +00:00
{
2009-05-01 20:31:17 +00:00
// Determine the shader pass we want to use for this object
2009-07-07 14:52:39 +00:00
int wantedshaderpass = ( ( ( g = = highlighted ) & & showhighlight ) | | ( g . Selected & & showselection ) ) ? highshaderpass : shaderpass ;
2012-05-13 20:51:41 +00:00
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
//mxd. Render fog?
Fixed, Visual mode: in some cases ceiling glow effect was interfering with Transfer Brightness effect resulting in incorrectly lit sidedef geometry.
Fixed, Visual mode: UDMF sidedef brightness should be ignored when a wall section is affected by Transfer Brightness effect.
Fixed, Visual mode: any custom fog should be rendered regardless of sector brightness.
Fixed, Visual mode: "fogdensity" and "outsidefogdensity" MAPINFO values were processed incorrectly.
Fixed, Visual mode: in some cases Things were rendered twice during a render pass.
Fixed, Visual mode: floor glow effect should affect thing brightness only when applied to floor of the sector thing is in.
Fixed, TEXTURES parser: TEXTURES group was named incorrectly in the Textures Browser window when parsed from a WAD file.
Fixed, MAPINFO, GLDEFS, DECORATE parsers: "//$GZDB_SKIP" special comment was processed incorrectly.
Fixed, MAPINFO parser: "fogdensity" and "outsidefogdensity" properties are now initialized using GZDoom default value (255) instead of 0.
2016-01-25 13:42:53 +00:00
if ( General . Settings . GZDrawFog & & ! fullbrightness & & sector . Sector . FogMode ! = SectorFogMode . NONE )
2013-09-11 09:47:53 +00:00
wantedshaderpass + = 8 ;
2009-05-01 20:31:17 +00:00
// Switch shader pass?
if ( currentshaderpass ! = wantedshaderpass )
2009-04-19 18:07:22 +00:00
{
graphics . Shaders . World3D . EndPass ( ) ;
2009-05-01 20:31:17 +00:00
graphics . Shaders . World3D . BeginPass ( wantedshaderpass ) ;
currentshaderpass = wantedshaderpass ;
2015-10-02 14:47:34 +00:00
//mxd. Set variables for fog rendering?
if ( wantedshaderpass > 7 )
{
graphics . Shaders . World3D . World = world ;
}
2009-04-19 18:07:22 +00:00
}
2015-10-02 14:47:34 +00:00
//mxd. Set variables for fog rendering?
if ( wantedshaderpass > 7 )
2009-05-04 06:13:56 +00:00
{
2015-12-01 14:51:45 +00:00
graphics . Shaders . World3D . CameraPosition = new Vector4 ( cameraposition . x , cameraposition . y , cameraposition . z , g . FogFactor ) ;
2015-10-02 14:47:34 +00:00
graphics . Shaders . World3D . LightColor = sector . Sector . FogColor ;
2009-05-04 06:13:56 +00:00
}
2018-04-10 16:41:35 +00:00
2015-10-02 14:47:34 +00:00
// Set the colors to use
graphics . Shaders . World3D . HighlightColor = CalculateHighlightColor ( ( g = = highlighted ) & & showhighlight , ( g . Selected & & showselection ) ) ;
2018-04-10 16:41:35 +00:00
// [ZZ] include desaturation factor
graphics . Shaders . World3D . Desaturation = sector . Sector . Desaturation ;
2015-10-02 14:47:34 +00:00
// Apply changes
graphics . Shaders . World3D . ApplySettings ( ) ;
2009-05-01 20:31:17 +00:00
2009-04-19 18:07:22 +00:00
// Render!
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , g . VertexOffset , g . Triangles ) ;
}
}
}
// Get things for this pass
2009-04-26 20:20:40 +00:00
if ( thingspass . Count > 0 )
2009-04-19 18:07:22 +00:00
{
2009-04-26 20:20:40 +00:00
// Texture addressing
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressU , TextureAddress . Clamp ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressV , TextureAddress . Clamp ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressW , TextureAddress . Clamp ) ;
Model rendering (all modes): UDMF scale, pitch and roll are now displayed.
Thing Edit Form, UDMF: added controls for setting pitch, roll, scale, render style, fill color, alpha, health and score.
Visual mode, UDMF: UDMF scale is now applied when rendering sprites.
Added Thing Statistics form (Edit -> View Thing Types...), which shows all loaded thing types with some additional info.
Visual mode: sprites with negative ScaleX and positive ScaleY were not rendered properly.
Classic modes: display was not updated after loading a sprite.
Current testing engine change was not saved on closing the program when no other game configuration settings were changed.
2014-04-30 10:01:22 +00:00
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ; //mxd. Disable backside culling, because otherwise sprites with positive ScaleY and negative ScaleX will be facing away from the camera...
2009-04-19 18:07:22 +00:00
2015-10-02 14:47:34 +00:00
Color4 vertexcolor = new Color4 ( ) ; //mxd
2009-04-26 20:20:40 +00:00
// Render things collected
foreach ( KeyValuePair < ImageData , List < VisualThing > > group in thingspass )
2009-04-19 18:07:22 +00:00
{
2015-09-27 21:09:14 +00:00
if ( group . Key is UnknownImage ) continue ;
// What texture to use?
if ( ! group . Key . IsImageLoaded | | group . Key . IsDisposed )
curtexture = General . Map . Data . Hourglass3D ;
else
curtexture = group . Key ;
// Create Direct3D texture if still needed
if ( ( curtexture . Texture = = null ) | | curtexture . Texture . Disposed )
curtexture . CreateTexture ( ) ;
// Apply texture
graphics . Shaders . World3D . Texture1 = curtexture . Texture ;
// Render all things with this texture
foreach ( VisualThing t in group . Value )
{
// Update buffer if needed
t . Update ( ) ;
2017-03-08 03:35:56 +00:00
//mxd. Check 3D distance
if ( t . Info . DistanceCheckSq < int . MaxValue & & ( t . Thing . Position - cameraposition ) . GetLengthSq ( ) > t . Info . DistanceCheckSq )
2016-04-13 10:07:46 +00:00
continue ;
2015-09-27 21:09:14 +00:00
// Only do this sector when a vertexbuffer is created
if ( t . GeometryBuffer ! = null )
2009-04-26 20:20:40 +00:00
{
2015-09-27 21:09:14 +00:00
// Determine the shader pass we want to use for this object
int wantedshaderpass = ( ( ( t = = highlighted ) & & showhighlight ) | | ( t . Selected & & showselection ) ) ? highshaderpass : shaderpass ;
2012-04-17 19:13:47 +00:00
2015-10-02 14:47:34 +00:00
//mxd. If fog is enagled, switch to shader, which calculates it
Fixed, Visual mode: in some cases ceiling glow effect was interfering with Transfer Brightness effect resulting in incorrectly lit sidedef geometry.
Fixed, Visual mode: UDMF sidedef brightness should be ignored when a wall section is affected by Transfer Brightness effect.
Fixed, Visual mode: any custom fog should be rendered regardless of sector brightness.
Fixed, Visual mode: "fogdensity" and "outsidefogdensity" MAPINFO values were processed incorrectly.
Fixed, Visual mode: in some cases Things were rendered twice during a render pass.
Fixed, Visual mode: floor glow effect should affect thing brightness only when applied to floor of the sector thing is in.
Fixed, TEXTURES parser: TEXTURES group was named incorrectly in the Textures Browser window when parsed from a WAD file.
Fixed, MAPINFO, GLDEFS, DECORATE parsers: "//$GZDB_SKIP" special comment was processed incorrectly.
Fixed, MAPINFO parser: "fogdensity" and "outsidefogdensity" properties are now initialized using GZDoom default value (255) instead of 0.
2016-01-25 13:42:53 +00:00
if ( General . Settings . GZDrawFog & & ! fullbrightness & & t . Thing . Sector ! = null & & t . Thing . Sector . FogMode ! = SectorFogMode . NONE )
2015-09-27 21:09:14 +00:00
wantedshaderpass + = 8 ;
2013-09-11 09:47:53 +00:00
2015-10-02 14:47:34 +00:00
//mxd. Create the matrix for positioning
world = CreateThingPositionMatrix ( t ) ;
//mxd. If current thing is light - set it's color to light color
2018-02-03 20:31:34 +00:00
if ( t . LightType ! = null & & t . LightType . LightInternal & & ! fullbrightness )
2015-09-27 21:09:14 +00:00
{
2015-10-02 14:47:34 +00:00
wantedshaderpass + = 4 ; // Render using one of passes, which uses World3D.VertexColor
vertexcolor = t . LightColor ;
2015-09-27 21:09:14 +00:00
}
2015-10-02 14:47:34 +00:00
//mxd. Check if Thing is affected by dynamic lights and set color accordingly
else if ( General . Settings . GZDrawLightsMode ! = LightRenderMode . NONE & & ! fullbrightness & & lightthings . Count > 0 )
2015-09-27 21:09:14 +00:00
{
2016-03-23 21:26:26 +00:00
Color4 litcolor = GetLitColorForThing ( t ) ;
2015-10-02 14:47:34 +00:00
if ( litcolor . ToArgb ( ) ! = 0 )
2014-10-20 12:16:51 +00:00
{
2015-10-02 14:47:34 +00:00
wantedshaderpass + = 4 ; // Render using one of passes, which uses World3D.VertexColor
vertexcolor = new Color4 ( t . VertexColor ) + litcolor ;
2013-09-11 09:47:53 +00:00
}
2015-09-27 21:09:14 +00:00
}
2015-10-02 14:47:34 +00:00
else
{
vertexcolor = new Color4 ( ) ;
}
2013-09-11 09:47:53 +00:00
2015-09-27 21:09:14 +00:00
// Switch shader pass?
if ( currentshaderpass ! = wantedshaderpass )
{
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Shaders . World3D . BeginPass ( wantedshaderpass ) ;
currentshaderpass = wantedshaderpass ;
}
2013-09-11 09:47:53 +00:00
2015-10-02 14:47:34 +00:00
//mxd. Set variables for fog rendering?
if ( wantedshaderpass > 7 )
2015-09-27 21:09:14 +00:00
{
2015-10-02 14:47:34 +00:00
graphics . Shaders . World3D . World = world ;
2016-03-23 21:26:26 +00:00
graphics . Shaders . World3D . CameraPosition = new Vector4 ( cameraposition . x , cameraposition . y , cameraposition . z , t . FogFactor ) ;
2015-09-27 21:09:14 +00:00
}
Model rendering (all modes): UDMF scale, pitch and roll are now displayed.
Thing Edit Form, UDMF: added controls for setting pitch, roll, scale, render style, fill color, alpha, health and score.
Visual mode, UDMF: UDMF scale is now applied when rendering sprites.
Added Thing Statistics form (Edit -> View Thing Types...), which shows all loaded thing types with some additional info.
Visual mode: sprites with negative ScaleX and positive ScaleY were not rendered properly.
Classic modes: display was not updated after loading a sprite.
Current testing engine change was not saved on closing the program when no other game configuration settings were changed.
2014-04-30 10:01:22 +00:00
2015-10-02 14:47:34 +00:00
// Set the colors to use
if ( t . Thing . Sector ! = null ) graphics . Shaders . World3D . LightColor = t . Thing . Sector . FogColor ;
graphics . Shaders . World3D . VertexColor = vertexcolor ;
graphics . Shaders . World3D . HighlightColor = CalculateHighlightColor ( ( t = = highlighted ) & & showhighlight , ( t . Selected & & showselection ) ) ;
2012-05-20 00:56:59 +00:00
2017-03-25 03:19:42 +00:00
// [ZZ] check if we want stencil
graphics . Shaders . World3D . StencilColor = t . StencilColor . ToColorValue ( ) ;
2018-04-10 16:41:35 +00:00
// [ZZ] apply desaturation
if ( t . Thing . Sector ! = null )
graphics . Shaders . World3D . Desaturation = t . Thing . Sector . Desaturation ;
2017-03-25 03:19:42 +00:00
// Apply changes
ApplyMatrices3D ( ) ;
2015-09-27 21:09:14 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
2012-04-17 19:13:47 +00:00
2015-09-27 21:09:14 +00:00
// Apply buffer
graphics . Device . SetStreamSource ( 0 , t . GeometryBuffer , 0 , WorldVertex . Stride ) ;
2012-04-17 19:13:47 +00:00
2015-09-27 21:09:14 +00:00
// Render!
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , 0 , t . Triangles ) ;
2017-03-25 03:19:42 +00:00
}
2009-04-19 18:07:22 +00:00
}
2012-04-17 19:13:47 +00:00
2017-03-25 03:19:42 +00:00
// [ZZ]
graphics . Shaders . World3D . StencilColor = new Color4 ( 0f , 1f , 1f , 1f ) ;
}
// Texture addressing
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressU , TextureAddress . Wrap ) ;
2013-09-11 09:47:53 +00:00
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressV , TextureAddress . Wrap ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressW , TextureAddress . Wrap ) ;
Model rendering (all modes): UDMF scale, pitch and roll are now displayed.
Thing Edit Form, UDMF: added controls for setting pitch, roll, scale, render style, fill color, alpha, health and score.
Visual mode, UDMF: UDMF scale is now applied when rendering sprites.
Added Thing Statistics form (Edit -> View Thing Types...), which shows all loaded thing types with some additional info.
Visual mode: sprites with negative ScaleX and positive ScaleY were not rendered properly.
Classic modes: display was not updated after loading a sprite.
Current testing engine change was not saved on closing the program when no other game configuration settings were changed.
2014-04-30 10:01:22 +00:00
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . Counterclockwise ) ; //mxd
2009-04-19 18:07:22 +00:00
}
// Done rendering with this shader
graphics . Shaders . World3D . EndPass ( ) ;
}
2009-05-05 21:13:50 +00:00
2015-09-27 21:09:14 +00:00
//mxd
private void RenderTranslucentPass ( List < VisualGeometry > geopass , List < VisualThing > thingspass )
{
int currentshaderpass = shaderpass ;
int highshaderpass = shaderpass + 2 ;
// Sort geometry by camera distance. First vertex of the BoundingBox is it's center
2017-04-29 10:56:06 +00:00
geopass . Sort ( delegate ( VisualGeometry vg1 , VisualGeometry vg2 )
2015-09-27 21:09:14 +00:00
{
2017-04-29 10:56:06 +00:00
/ * if ( vg1 = = vg2 ) return 0 ;
return ( int ) ( ( General . Map . VisualCamera . Position - vg2 . BoundingBox [ 0 ] ) . GetLengthSq ( )
- ( General . Map . VisualCamera . Position - vg1 . BoundingBox [ 0 ] ) . GetLengthSq ( ) ) ; * /
// This does not work when you have huge translucent 3D floor combined with small translucent something over it.
// The huge translucent 3D floor may easily have it's center CLOSER and thus get drawn over everything, which is certainly not expected behavior.
if ( vg1 = = vg2 )
return 0 ;
double dist1 , dist2 ;
Vector3D cameraPos = General . Map . VisualCamera . Position ;
Vector2D cameraPos2 = new Vector2D ( cameraPos ) ;
// if one of the things being compared is a plane, use easier formula. (3d floor compatibility)
if ( vg1 . GeometryType = = VisualGeometryType . FLOOR | | vg1 . GeometryType = = VisualGeometryType . CEILING | |
vg2 . GeometryType = = VisualGeometryType . FLOOR | | vg2 . GeometryType = = VisualGeometryType . CEILING )
{
// more magic
dist1 = Math . Abs ( vg1 . BoundingBox [ 0 ] . z - cameraPos . z ) ;
dist2 = Math . Abs ( vg2 . BoundingBox [ 0 ] . z - cameraPos . z ) ;
}
else
{
dist1 = ( General . Map . VisualCamera . Position - vg1 . BoundingBox [ 0 ] ) . GetLengthSq ( ) ;
dist2 = ( General . Map . VisualCamera . Position - vg2 . BoundingBox [ 0 ] ) . GetLengthSq ( ) ;
}
2015-09-27 21:09:14 +00:00
2017-04-29 10:56:06 +00:00
return ( int ) ( dist2 - dist1 ) ;
} ) ;
2015-09-27 21:09:14 +00:00
2015-10-02 14:47:34 +00:00
ImageData curtexture ;
2015-09-27 21:09:14 +00:00
VisualSector sector = null ;
RenderPass currentpass = RenderPass . Solid ;
long curtexturename = 0 ;
2015-10-02 14:47:34 +00:00
float fogfactor = - 1 ;
// Begin rendering with this shader
graphics . Shaders . World3D . BeginPass ( shaderpass ) ;
2015-09-27 21:09:14 +00:00
// Go for all geometry
foreach ( VisualGeometry g in geopass )
{
// Change blend mode?
if ( g . RenderPass ! = currentpass )
{
switch ( g . RenderPass )
{
case RenderPass . Additive :
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . One ) ;
break ;
case RenderPass . Alpha :
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . InverseSourceAlpha ) ;
break ;
}
currentpass = g . RenderPass ;
}
// Change texture?
if ( g . Texture . LongName ! = curtexturename )
{
// What texture to use?
if ( g . Texture is UnknownImage )
curtexture = General . Map . Data . UnknownTexture3D ;
else if ( g . Texture . IsImageLoaded & & ! g . Texture . IsDisposed )
curtexture = g . Texture ;
else
curtexture = General . Map . Data . Hourglass3D ;
// Create Direct3D texture if still needed
if ( ( curtexture . Texture = = null ) | | curtexture . Texture . Disposed )
curtexture . CreateTexture ( ) ;
// Apply texture
graphics . Shaders . World3D . Texture1 = curtexture . Texture ;
curtexturename = g . Texture . LongName ;
}
// Changing sector?
if ( ! object . ReferenceEquals ( g . Sector , sector ) )
{
// Update the sector if needed
if ( g . Sector . NeedsUpdateGeo ) g . Sector . Update ( ) ;
// Only do this sector when a vertexbuffer is created
2015-10-02 14:47:34 +00:00
//mxd. No Map means that sector was deleted recently, I suppose
2015-09-27 21:09:14 +00:00
if ( g . Sector . GeometryBuffer ! = null & & g . Sector . Sector . Map ! = null )
{
// Change current sector
sector = g . Sector ;
// Set stream source
graphics . Device . SetStreamSource ( 0 , sector . GeometryBuffer , 0 , WorldVertex . Stride ) ;
}
else
{
sector = null ;
}
}
2018-04-10 16:41:35 +00:00
if ( sector ! = null )
{
// Determine the shader pass we want to use for this object
int wantedshaderpass = ( ( ( g = = highlighted ) & & showhighlight ) | | ( g . Selected & & showselection ) ) ? highshaderpass : shaderpass ;
2015-09-27 21:09:14 +00:00
2018-04-10 16:41:35 +00:00
//mxd. Render fog?
if ( General . Settings . GZDrawFog & & ! fullbrightness & & sector . Sector . FogMode ! = SectorFogMode . NONE )
wantedshaderpass + = 8 ;
2015-09-27 21:09:14 +00:00
2018-04-10 16:41:35 +00:00
// Switch shader pass?
if ( currentshaderpass ! = wantedshaderpass )
{
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Shaders . World3D . BeginPass ( wantedshaderpass ) ;
currentshaderpass = wantedshaderpass ;
2015-09-27 21:09:14 +00:00
2018-04-10 16:41:35 +00:00
//mxd. Set variables for fog rendering?
if ( wantedshaderpass > 7 )
{
graphics . Shaders . World3D . World = world ;
}
}
2015-09-27 21:09:14 +00:00
2018-04-10 16:41:35 +00:00
// Set variables for fog rendering?
if ( wantedshaderpass > 7 & & g . FogFactor ! = fogfactor )
{
graphics . Shaders . World3D . CameraPosition = new Vector4 ( cameraposition . x , cameraposition . y , cameraposition . z , g . FogFactor ) ;
fogfactor = g . FogFactor ;
}
2015-09-27 21:09:14 +00:00
2018-04-10 16:41:35 +00:00
//
graphics . Shaders . World3D . Desaturation = sector . Sector . Desaturation ;
2015-10-02 14:47:34 +00:00
2018-04-10 16:41:35 +00:00
// Set the colors to use
graphics . Shaders . World3D . LightColor = sector . Sector . FogColor ;
graphics . Shaders . World3D . HighlightColor = CalculateHighlightColor ( ( g = = highlighted ) & & showhighlight , ( g . Selected & & showselection ) ) ;
2015-10-02 14:47:34 +00:00
2018-04-10 16:41:35 +00:00
// Apply changes
graphics . Shaders . World3D . ApplySettings ( ) ;
// Render!
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , g . VertexOffset , g . Triangles ) ;
}
else graphics . Shaders . World3D . Desaturation = 0f ;
}
2015-09-27 21:09:14 +00:00
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
// Get things for this pass
if ( thingspass . Count > 0 )
{
// Texture addressing
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressU , TextureAddress . Clamp ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressV , TextureAddress . Clamp ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressW , TextureAddress . Clamp ) ;
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ; //mxd. Disable backside culling, because otherwise sprites with positive ScaleY and negative ScaleX will be facing away from the camera...
// Sort geometry by camera distance. First vertex of the BoundingBox is it's center
2016-01-11 13:00:52 +00:00
thingspass . Sort ( delegate ( VisualThing vt1 , VisualThing vt2 )
{
if ( vt1 = = vt2 ) return 0 ;
return ( int ) ( ( General . Map . VisualCamera . Position - vt2 . BoundingBox [ 0 ] ) . GetLengthSq ( )
- ( General . Map . VisualCamera . Position - vt1 . BoundingBox [ 0 ] ) . GetLengthSq ( ) ) ;
} ) ;
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
// Reset vars
currentpass = RenderPass . Solid ;
curtexturename = 0 ;
2015-10-02 14:47:34 +00:00
Color4 vertexcolor = new Color4 ( ) ;
fogfactor = - 1 ;
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
// Render things collected
foreach ( VisualThing t in thingspass )
{
2016-04-13 10:07:46 +00:00
// Update buffer if needed
t . Update ( ) ;
//mxd. Check 3D distance
if ( t . Info . DistanceCheckSq < int . MaxValue & & ( t . Thing . Position - cameraposition ) . GetLengthSq ( ) > t . Info . DistanceCheckSq )
continue ;
2016-04-11 23:05:16 +00:00
t . UpdateSpriteFrame ( ) ; // Set correct texture, geobuffer and triangles count
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
if ( t . Texture is UnknownImage ) continue ;
// Change blend mode?
if ( t . RenderPass ! = currentpass )
{
switch ( t . RenderPass )
{
case RenderPass . Additive :
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . One ) ;
break ;
case RenderPass . Alpha :
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . InverseSourceAlpha ) ;
break ;
}
currentpass = t . RenderPass ;
}
// Change texture?
if ( t . Texture . LongName ! = curtexturename )
{
// What texture to use?
if ( t . Texture . IsImageLoaded & & ! t . Texture . IsDisposed )
curtexture = t . Texture ;
else
curtexture = General . Map . Data . Hourglass3D ;
// Create Direct3D texture if still needed
if ( ( curtexture . Texture = = null ) | | curtexture . Texture . Disposed )
curtexture . CreateTexture ( ) ;
// Apply texture
graphics . Shaders . World3D . Texture1 = curtexture . Texture ;
curtexturename = t . Texture . LongName ;
}
// Only do this sector when a vertexbuffer is created
if ( t . GeometryBuffer ! = null )
{
// Determine the shader pass we want to use for this object
int wantedshaderpass = ( ( ( t = = highlighted ) & & showhighlight ) | | ( t . Selected & & showselection ) ) ? highshaderpass : shaderpass ;
//mxd. if fog is enagled, switch to shader, which calculates it
Fixed, Visual mode: in some cases ceiling glow effect was interfering with Transfer Brightness effect resulting in incorrectly lit sidedef geometry.
Fixed, Visual mode: UDMF sidedef brightness should be ignored when a wall section is affected by Transfer Brightness effect.
Fixed, Visual mode: any custom fog should be rendered regardless of sector brightness.
Fixed, Visual mode: "fogdensity" and "outsidefogdensity" MAPINFO values were processed incorrectly.
Fixed, Visual mode: in some cases Things were rendered twice during a render pass.
Fixed, Visual mode: floor glow effect should affect thing brightness only when applied to floor of the sector thing is in.
Fixed, TEXTURES parser: TEXTURES group was named incorrectly in the Textures Browser window when parsed from a WAD file.
Fixed, MAPINFO, GLDEFS, DECORATE parsers: "//$GZDB_SKIP" special comment was processed incorrectly.
Fixed, MAPINFO parser: "fogdensity" and "outsidefogdensity" properties are now initialized using GZDoom default value (255) instead of 0.
2016-01-25 13:42:53 +00:00
if ( General . Settings . GZDrawFog & & ! fullbrightness & & t . Thing . Sector ! = null & & t . Thing . Sector . FogMode ! = SectorFogMode . NONE )
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
wantedshaderpass + = 8 ;
2015-10-02 14:47:34 +00:00
//mxd. Create the matrix for positioning
world = CreateThingPositionMatrix ( t ) ;
//mxd. If current thing is light - set it's color to light color
2018-02-03 20:31:34 +00:00
if ( t . LightType ! = null & & t . LightType . LightInternal & & ! fullbrightness )
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
{
2015-10-02 14:47:34 +00:00
wantedshaderpass + = 4 ; // Render using one of passes, which uses World3D.VertexColor
vertexcolor = t . LightColor ;
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
}
2015-10-02 14:47:34 +00:00
//mxd. Check if Thing is affected by dynamic lights and set color accordingly
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
else if ( General . Settings . GZDrawLightsMode ! = LightRenderMode . NONE & & ! fullbrightness & & lightthings . Count > 0 )
{
2016-03-23 21:26:26 +00:00
Color4 litcolor = GetLitColorForThing ( t ) ;
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
if ( litcolor . ToArgb ( ) ! = 0 )
{
2015-10-02 14:47:34 +00:00
wantedshaderpass + = 4 ; // Render using one of passes, which uses World3D.VertexColor
vertexcolor = new Color4 ( t . VertexColor ) + litcolor ;
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
}
}
2015-10-02 14:47:34 +00:00
else
{
vertexcolor = new Color4 ( ) ;
}
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
// Switch shader pass?
if ( currentshaderpass ! = wantedshaderpass )
{
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Shaders . World3D . BeginPass ( wantedshaderpass ) ;
currentshaderpass = wantedshaderpass ;
}
2016-03-23 21:26:26 +00:00
//mxd. Set variables for fog rendering?
2015-10-02 14:47:34 +00:00
if ( wantedshaderpass > 7 )
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
{
2015-10-02 14:47:34 +00:00
graphics . Shaders . World3D . World = world ;
2016-03-23 21:26:26 +00:00
if ( t . FogFactor ! = fogfactor )
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
{
2016-03-23 21:26:26 +00:00
graphics . Shaders . World3D . CameraPosition = new Vector4 ( cameraposition . x , cameraposition . y , cameraposition . z , t . FogFactor ) ;
fogfactor = t . FogFactor ;
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
}
}
2015-10-02 14:47:34 +00:00
// Set the colors to use
graphics . Shaders . World3D . LightColor = t . Thing . Sector . FogColor ;
graphics . Shaders . World3D . VertexColor = vertexcolor ;
graphics . Shaders . World3D . HighlightColor = CalculateHighlightColor ( ( t = = highlighted ) & & showhighlight , ( t . Selected & & showselection ) ) ;
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
2017-03-25 03:19:42 +00:00
// [ZZ] check if we want stencil
graphics . Shaders . World3D . StencilColor = t . StencilColor . ToColorValue ( ) ;
2018-04-10 16:41:35 +00:00
//
graphics . Shaders . World3D . Desaturation = t . Thing . Sector . Desaturation ;
2017-03-25 03:19:42 +00:00
// Apply changes
ApplyMatrices3D ( ) ;
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
// Apply buffer
graphics . Device . SetStreamSource ( 0 , t . GeometryBuffer , 0 , WorldVertex . Stride ) ;
// Render!
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , 0 , t . Triangles ) ;
}
}
2017-03-25 03:19:42 +00:00
// [ZZ] check if we want stencil
graphics . Shaders . World3D . StencilColor = new Color4 ( 0f , 1f , 1f , 1f ) ;
// Texture addressing
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressU , TextureAddress . Wrap ) ;
Added, Visual mode, DECORATE: "Alpha" and "DefaultAlpha" properties are now supported.
Added, Visual mode, DECORATE: "RenderStyle" property is now partially supported.
Added, Visual mode, DECORATE: +BRIGHT flag is now supported.
Added, Visual mode, UDMF: "Alpha" thing property is now supported.
Added, Visual mode, UDMF: "RenderStyle" thing property is now partially supported.
Added, Visual mode, Hexen map format and UDMF: "Translucent" and "Invisible" thing flags are now supported.
Added, Game Configurations: added "alpha" and "renderstyle" Thing and Thing Category properties.
Fixed, Visual mode: blockmap was not updated when moving things using "Move Thing Left/Right/Forward/Backward" and "Move Thing to Cursor Location" actions.
DECORATE parser: added a warning when unable to find actor's parent class.
Internal: current map format can now be checked using "General.Map.UDMF", "General.Map.HEXEN" and "General.Map.DOOM" properties.
Updated documentation ("Game Configuration - Things Settings" page).
2015-09-28 14:57:48 +00:00
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressV , TextureAddress . Wrap ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressW , TextureAddress . Wrap ) ;
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . Counterclockwise ) ; //mxd
}
2015-09-27 21:09:14 +00:00
// Done rendering with this shader
graphics . Shaders . World3D . EndPass ( ) ;
}
2015-10-02 14:47:34 +00:00
//mxd
private Matrix CreateThingPositionMatrix ( VisualThing t )
{
2016-07-11 22:13:43 +00:00
// Use normal ThingRenderMode when model rendering is disabled for this thing
ThingRenderMode rendermode = t . Thing . RenderMode ;
if ( ( t . Thing . RenderMode = = ThingRenderMode . MODEL | | t . Thing . RenderMode = = ThingRenderMode . VOXEL ) & &
( General . Settings . GZDrawModelsMode = = ModelRenderMode . NONE | |
( General . Settings . GZDrawModelsMode = = ModelRenderMode . SELECTION & & ! t . Selected ) ) )
{
rendermode = ThingRenderMode . NORMAL ;
}
2016-07-04 18:25:47 +00:00
// Create the matrix for positioning
2016-07-11 22:13:43 +00:00
switch ( rendermode )
2015-10-02 14:47:34 +00:00
{
2016-07-04 18:25:47 +00:00
case ThingRenderMode . NORMAL :
if ( t . Info . XYBillboard ) // Apply billboarding?
{
return Matrix . Translation ( 0f , 0f , - t . LocalCenterZ )
* Matrix . RotationX ( Angle2D . PI - General . Map . VisualCamera . AngleZ )
* Matrix . Translation ( 0f , 0f , t . LocalCenterZ )
* billboard
2015-10-02 14:47:34 +00:00
* t . Position ;
2016-07-04 18:25:47 +00:00
}
2016-10-04 09:53:38 +00:00
return billboard * t . Position ;
2016-07-04 18:25:47 +00:00
case ThingRenderMode . FLATSPRITE :
case ThingRenderMode . WALLSPRITE :
case ThingRenderMode . MODEL :
2016-07-11 22:13:43 +00:00
case ThingRenderMode . VOXEL :
2016-10-04 09:53:38 +00:00
return t . Position ;
2016-07-04 18:25:47 +00:00
default : throw new NotImplementedException ( "Unknown ThingRenderMode" ) ;
2015-10-02 14:47:34 +00:00
}
}
2018-02-04 02:18:59 +00:00
private float CosDeg ( float angle )
{
return ( float ) Math . Cos ( Angle2D . DegToRad ( angle ) ) ;
}
2017-02-09 13:03:22 +00:00
//mxd. Dynamic lights pass!
private VisualSector RenderLightsFromGeometryList ( List < VisualGeometry > geometrytolit , List < VisualThing > lights , VisualSector sector , bool settexture )
{
foreach ( VisualGeometry g in geometrytolit )
{
// Changing sector?
if ( ! object . ReferenceEquals ( g . Sector , sector ) )
{
// Only do this sector when a vertexbuffer is created
// mxd. no Map means that sector was deleted recently, I suppose
if ( g . Sector . GeometryBuffer ! = null & & g . Sector . Sector . Map ! = null )
{
// Change current sector
sector = g . Sector ;
2012-04-18 19:34:11 +00:00
2017-02-09 13:03:22 +00:00
// Set stream source
graphics . Device . SetStreamSource ( 0 , sector . GeometryBuffer , 0 , WorldVertex . Stride ) ;
}
else
{
sector = null ;
}
}
2012-04-18 19:34:11 +00:00
2017-02-09 13:03:22 +00:00
if ( sector = = null ) continue ;
2012-04-18 19:34:11 +00:00
2018-04-10 16:41:35 +00:00
graphics . Shaders . World3D . Desaturation = sector . Sector . Desaturation ;
2017-02-09 14:49:58 +00:00
// note: additive geometry doesn't receive lighting
if ( g . RenderPass = = RenderPass . Additive )
continue ;
2017-02-09 13:03:22 +00:00
if ( settexture )
graphics . Shaders . World3D . Texture1 = g . Texture . Texture ;
2012-04-18 19:34:11 +00:00
2017-02-09 13:03:22 +00:00
//normal lights
int count = lightOffsets [ 0 ] ;
Vector4 lpr ;
if ( lightOffsets [ 0 ] > 0 )
{
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . Add ) ;
2015-09-27 21:09:14 +00:00
2017-02-09 13:03:22 +00:00
for ( int i = 0 ; i < count ; i + + )
{
if ( BoundingBoxesIntersect ( g . BoundingBox , lights [ i ] . BoundingBox ) )
{
lpr = new Vector4 ( lights [ i ] . Center , lights [ i ] . LightRadius ) ;
if ( lpr . W = = 0 ) continue ;
graphics . Shaders . World3D . LightColor = lights [ i ] . LightColor ;
graphics . Shaders . World3D . LightPositionAndRadius = lpr ;
2018-02-04 02:18:59 +00:00
GZGeneral . LightData ld = lights [ i ] . LightType ;
if ( ld . LightType = = GZGeneral . LightType . SPOT )
{
graphics . Shaders . World3D . SpotLight = true ;
graphics . Shaders . World3D . LightOrientation = lights [ i ] . VectorLookAt ;
graphics . Shaders . World3D . Light2Radius = new Vector2 ( CosDeg ( lights [ i ] . LightSpotRadius1 ) , CosDeg ( lights [ i ] . LightSpotRadius2 ) ) ;
}
else graphics . Shaders . World3D . SpotLight = false ;
2017-02-09 13:03:22 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , g . VertexOffset , g . Triangles ) ;
}
}
}
2015-09-27 21:09:14 +00:00
2017-02-09 13:03:22 +00:00
//attenuated lights
if ( lightOffsets [ 1 ] > 0 )
{
count + = lightOffsets [ 1 ] ;
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . Add ) ;
2012-04-18 19:34:11 +00:00
2017-02-09 13:03:22 +00:00
for ( int i = lightOffsets [ 0 ] ; i < count ; i + + )
{
if ( BoundingBoxesIntersect ( g . BoundingBox , lights [ i ] . BoundingBox ) )
{
lpr = new Vector4 ( lights [ i ] . Center , lights [ i ] . LightRadius ) ;
if ( lpr . W = = 0 ) continue ;
graphics . Shaders . World3D . LightColor = lights [ i ] . LightColor ;
graphics . Shaders . World3D . LightPositionAndRadius = lpr ;
2018-02-04 02:18:59 +00:00
GZGeneral . LightData ld = lights [ i ] . LightType ;
if ( ld . LightType = = GZGeneral . LightType . SPOT )
{
graphics . Shaders . World3D . SpotLight = true ;
graphics . Shaders . World3D . LightOrientation = lights [ i ] . VectorLookAt ;
graphics . Shaders . World3D . Light2Radius = new Vector2 ( CosDeg ( lights [ i ] . LightSpotRadius1 ) , CosDeg ( lights [ i ] . LightSpotRadius2 ) ) ;
}
else graphics . Shaders . World3D . SpotLight = false ;
2017-02-09 13:03:22 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , g . VertexOffset , g . Triangles ) ;
}
}
}
2012-04-18 19:34:11 +00:00
2017-02-09 13:03:22 +00:00
//additive lights
if ( lightOffsets [ 2 ] > 0 )
{
count + = lightOffsets [ 2 ] ;
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . Add ) ;
2013-09-11 09:47:53 +00:00
2017-02-09 13:03:22 +00:00
for ( int i = lightOffsets [ 0 ] + lightOffsets [ 1 ] ; i < count ; i + + )
2017-02-09 11:28:55 +00:00
{
2017-02-09 13:03:22 +00:00
if ( BoundingBoxesIntersect ( g . BoundingBox , lights [ i ] . BoundingBox ) )
{
lpr = new Vector4 ( lights [ i ] . Center , lights [ i ] . LightRadius ) ;
if ( lpr . W = = 0 ) continue ;
graphics . Shaders . World3D . LightColor = lights [ i ] . LightColor ;
graphics . Shaders . World3D . LightPositionAndRadius = lpr ;
2018-02-04 02:18:59 +00:00
GZGeneral . LightData ld = lights [ i ] . LightType ;
if ( ld . LightType = = GZGeneral . LightType . SPOT )
{
graphics . Shaders . World3D . SpotLight = true ;
graphics . Shaders . World3D . LightOrientation = lights [ i ] . VectorLookAt ;
graphics . Shaders . World3D . Light2Radius = new Vector2 ( CosDeg ( lights [ i ] . LightSpotRadius1 ) , CosDeg ( lights [ i ] . LightSpotRadius2 ) ) ;
}
else graphics . Shaders . World3D . SpotLight = false ;
2017-02-09 13:03:22 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , g . VertexOffset , g . Triangles ) ;
}
}
}
//negative lights
if ( lightOffsets [ 3 ] > 0 )
{
count + = lightOffsets [ 3 ] ;
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . ReverseSubtract ) ;
2017-02-09 11:28:55 +00:00
2017-02-09 13:03:22 +00:00
for ( int i = lightOffsets [ 0 ] + lightOffsets [ 1 ] + lightOffsets [ 2 ] ; i < count ; i + + )
{
if ( BoundingBoxesIntersect ( g . BoundingBox , lights [ i ] . BoundingBox ) )
2017-02-09 11:28:55 +00:00
{
2017-02-09 13:03:22 +00:00
lpr = new Vector4 ( lights [ i ] . Center , lights [ i ] . LightRadius ) ;
if ( lpr . W = = 0 ) continue ;
Color4 lc = lights [ i ] . LightColor ;
graphics . Shaders . World3D . LightColor = new Color4 ( lc . Alpha , ( lc . Green + lc . Blue ) / 2 , ( lc . Red + lc . Blue ) / 2 , ( lc . Green + lc . Red ) / 2 ) ;
graphics . Shaders . World3D . LightPositionAndRadius = lpr ;
2018-02-04 02:18:59 +00:00
GZGeneral . LightData ld = lights [ i ] . LightType ;
if ( ld . LightType = = GZGeneral . LightType . SPOT )
{
graphics . Shaders . World3D . SpotLight = true ;
graphics . Shaders . World3D . LightOrientation = lights [ i ] . VectorLookAt ;
graphics . Shaders . World3D . Light2Radius = new Vector2 ( CosDeg ( lights [ i ] . LightSpotRadius1 ) , CosDeg ( lights [ i ] . LightSpotRadius2 ) ) ;
}
else graphics . Shaders . World3D . SpotLight = false ;
2017-02-09 13:03:22 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , g . VertexOffset , g . Triangles ) ;
2017-02-09 11:28:55 +00:00
}
}
2017-02-09 13:03:22 +00:00
}
}
2017-02-09 11:28:55 +00:00
2017-02-09 13:03:22 +00:00
return sector ;
}
2018-02-04 02:18:59 +00:00
2017-02-09 13:03:22 +00:00
// [ZZ] split into RenderLights and RenderTranslucentLights
private void RenderTranslucentLights ( List < VisualGeometry > geometrytolit , List < VisualThing > lights )
{
if ( geometrytolit . Count = = 0 ) return ;
2013-09-11 09:47:53 +00:00
2017-02-09 13:03:22 +00:00
graphics . Shaders . World3D . World = Matrix . Identity ;
graphics . Shaders . World3D . BeginPass ( SHADERPASS_LIGHT ) ;
2013-09-11 09:47:53 +00:00
2017-02-09 13:03:22 +00:00
VisualSector sector = null ;
2013-09-11 09:47:53 +00:00
2017-02-09 13:03:22 +00:00
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . One ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . BlendFactor ) ;
//
RenderLightsFromGeometryList ( geometrytolit , lights , sector , true ) ;
//
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . Add ) ;
}
//
private void RenderLights ( Dictionary < ImageData , List < VisualGeometry > > geometrytolit , List < VisualThing > lights )
{
// Anything to do?
if ( geometrytolit . Count = = 0 ) return ;
graphics . Shaders . World3D . World = Matrix . Identity ;
graphics . Shaders . World3D . BeginPass ( SHADERPASS_LIGHT ) ;
VisualSector sector = null ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . One ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . BlendFactor ) ;
foreach ( KeyValuePair < ImageData , List < VisualGeometry > > group in geometrytolit )
{
if ( group . Key . Texture = = null ) continue ;
graphics . Shaders . World3D . Texture1 = group . Key . Texture ;
sector = RenderLightsFromGeometryList ( group . Value , lights , sector , false ) ;
}
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . Add ) ;
}
2013-09-11 09:47:53 +00:00
2017-02-09 13:03:22 +00:00
//mxd. Render models
2017-07-26 15:35:22 +00:00
private void RenderModels ( bool lightpass , bool trans )
2014-10-20 12:16:51 +00:00
{
2015-12-01 14:51:45 +00:00
int shaderpass = ( fullbrightness ? 1 : 4 ) ;
2013-09-11 09:47:53 +00:00
int currentshaderpass = shaderpass ;
int highshaderpass = shaderpass + 2 ;
2017-07-26 15:35:22 +00:00
RenderPass currentpass = RenderPass . Solid ;
2013-09-11 09:47:53 +00:00
2017-07-26 15:35:22 +00:00
// Begin rendering with this shader
if ( ! lightpass )
{
graphics . Shaders . World3D . BeginPass ( currentshaderpass ) ;
}
else
{
graphics . Shaders . World3D . BeginPass ( SHADERPASS_LIGHT ) ;
}
2015-12-01 14:51:45 +00:00
2017-07-26 15:35:22 +00:00
List < VisualThing > things ;
if ( trans )
{
// Sort models by camera distance. First vertex of the BoundingBox is it's center
translucentmodelthings . Sort ( ( vt1 , vt2 ) = > ( int ) ( ( General . Map . VisualCamera . Position - vt2 . BoundingBox [ 0 ] ) . GetLengthSq ( )
- ( General . Map . VisualCamera . Position - vt1 . BoundingBox [ 0 ] ) . GetLengthSq ( ) ) ) ;
things = translucentmodelthings ;
}
else
{
things = new List < VisualThing > ( ) ;
foreach ( KeyValuePair < ModelData , List < VisualThing > > group in maskedmodelthings )
foreach ( VisualThing t in group . Value )
things . Add ( t ) ;
}
foreach ( VisualThing t in things )
2015-12-01 14:51:45 +00:00
{
2017-07-26 15:35:22 +00:00
if ( trans )
{
// Change blend mode?
if ( t . RenderPass ! = currentpass )
{
switch ( t . RenderPass )
{
case RenderPass . Additive :
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . One ) ;
break ;
2015-12-01 14:51:45 +00:00
2017-07-26 15:35:22 +00:00
case RenderPass . Alpha :
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . InverseSourceAlpha ) ;
break ;
}
currentpass = t . RenderPass ;
}
}
2015-12-01 14:51:45 +00:00
2016-04-13 10:07:46 +00:00
// Update buffer if needed
2015-12-01 14:51:45 +00:00
t . Update ( ) ;
2016-04-13 10:07:46 +00:00
// Check 3D distance
if ( t . Info . DistanceCheckSq < int . MaxValue & & ( t . Thing . Position - cameraposition ) . GetLengthSq ( ) > t . Info . DistanceCheckSq )
continue ;
2017-07-26 15:35:22 +00:00
2015-12-01 14:51:45 +00:00
Color4 vertexcolor = new Color4 ( t . VertexColor ) ;
2017-07-26 15:35:22 +00:00
// Check if model is affected by dynamic lights and set color accordingly
graphics . Shaders . World3D . VertexColor = vertexcolor ;
2015-12-01 14:51:45 +00:00
// Determine the shader pass we want to use for this object
int wantedshaderpass = ( ( ( ( t = = highlighted ) & & showhighlight ) | | ( t . Selected & & showselection ) ) ? highshaderpass : shaderpass ) ;
2016-04-13 10:07:46 +00:00
// If fog is enagled, switch to shader, which calculates it
2017-07-26 15:35:22 +00:00
if ( General . Settings . GZDrawFog & & ! fullbrightness & & t . Thing . Sector ! = null & & t . Thing . Sector . FogMode ! = SectorFogMode . NONE )
2015-12-01 14:51:45 +00:00
wantedshaderpass + = 8 ;
// Switch shader pass?
2017-07-26 15:35:22 +00:00
if ( ! lightpass & & currentshaderpass ! = wantedshaderpass )
2015-12-01 14:51:45 +00:00
{
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Shaders . World3D . BeginPass ( wantedshaderpass ) ;
currentshaderpass = wantedshaderpass ;
}
// Set the colors to use
graphics . Shaders . World3D . HighlightColor = CalculateHighlightColor ( ( t = = highlighted ) & & showhighlight , ( t . Selected & & showselection ) ) ;
// Create the matrix for positioning / rotation
float sx = t . Thing . ScaleX * t . Thing . ActorScale . Width ;
float sy = t . Thing . ScaleY * t . Thing . ActorScale . Height ;
Matrix modelscale = Matrix . Scaling ( sx , sx , sy ) ;
2016-07-17 00:00:29 +00:00
Matrix modelrotation = Matrix . RotationY ( - t . Thing . RollRad ) * Matrix . RotationX ( - t . Thing . PitchRad ) * Matrix . RotationZ ( t . Thing . Angle ) ;
2015-12-01 14:51:45 +00:00
world = General . Map . Data . ModeldefEntries [ t . Thing . Type ] . Transform * modelscale * modelrotation * t . Position ;
ApplyMatrices3D ( ) ;
2016-04-13 10:07:46 +00:00
// Set variables for fog rendering
2015-12-01 14:51:45 +00:00
if ( wantedshaderpass > 7 )
{
graphics . Shaders . World3D . World = world ;
if ( t . Thing . Sector ! = null ) graphics . Shaders . World3D . LightColor = t . Thing . Sector . FogColor ;
2016-03-23 21:26:26 +00:00
graphics . Shaders . World3D . CameraPosition = new Vector4 ( cameraposition . x , cameraposition . y , cameraposition . z , t . FogFactor ) ;
2015-12-01 14:51:45 +00:00
}
2018-04-10 16:41:35 +00:00
graphics . Shaders . World3D . Desaturation = t . Thing . Sector . Desaturation ;
2017-07-26 15:35:22 +00:00
GZModel model = General . Map . Data . ModeldefEntries [ t . Thing . Type ] . Model ;
for ( int j = 0 ; j < model . Meshes . Count ; j + + )
{
graphics . Shaders . World3D . Texture1 = model . Textures [ j ] ;
graphics . Shaders . World3D . ApplySettings ( ) ;
2015-12-01 14:51:45 +00:00
2017-07-26 15:35:22 +00:00
if ( ! lightpass )
{
// Render!
model . Meshes [ j ] . DrawSubset ( 0 ) ;
}
else if ( lightpass & & t . RenderPass ! = RenderPass . Additive ) // additive stuff does not get any lighting
{
List < VisualThing > lights = lightthings ;
//
int count = lightOffsets [ 0 ] ;
Vector4 lpr ;
// normal lights
if ( lightOffsets [ 0 ] > 0 )
{
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . Add ) ;
for ( int i = 0 ; i < count ; i + + )
{
if ( BoundingBoxesIntersect ( t . BoundingBox , lights [ i ] . BoundingBox ) )
{
lpr = new Vector4 ( lights [ i ] . Center , lights [ i ] . LightRadius ) ;
if ( lpr . W = = 0 ) continue ;
graphics . Shaders . World3D . LightColor = lights [ i ] . LightColor ;
graphics . Shaders . World3D . LightPositionAndRadius = lpr ;
2018-02-04 02:18:59 +00:00
GZGeneral . LightData ld = lights [ i ] . LightType ;
if ( ld . LightType = = GZGeneral . LightType . SPOT )
{
graphics . Shaders . World3D . SpotLight = true ;
graphics . Shaders . World3D . LightOrientation = lights [ i ] . VectorLookAt ;
graphics . Shaders . World3D . Light2Radius = new Vector2 ( CosDeg ( lights [ i ] . LightSpotRadius1 ) , CosDeg ( lights [ i ] . LightSpotRadius2 ) ) ;
}
else graphics . Shaders . World3D . SpotLight = false ;
2017-07-26 15:35:22 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
model . Meshes [ j ] . DrawSubset ( 0 ) ;
}
}
}
//attenuated lights
if ( lightOffsets [ 1 ] > 0 )
{
count + = lightOffsets [ 1 ] ;
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . Add ) ;
for ( int i = lightOffsets [ 0 ] ; i < count ; i + + )
{
if ( BoundingBoxesIntersect ( t . BoundingBox , lights [ i ] . BoundingBox ) )
{
lpr = new Vector4 ( lights [ i ] . Center , lights [ i ] . LightRadius ) ;
if ( lpr . W = = 0 ) continue ;
graphics . Shaders . World3D . LightColor = lights [ i ] . LightColor ;
graphics . Shaders . World3D . LightPositionAndRadius = lpr ;
2018-02-04 02:18:59 +00:00
GZGeneral . LightData ld = lights [ i ] . LightType ;
if ( ld . LightType = = GZGeneral . LightType . SPOT )
{
graphics . Shaders . World3D . SpotLight = true ;
graphics . Shaders . World3D . LightOrientation = lights [ i ] . VectorLookAt ;
graphics . Shaders . World3D . Light2Radius = new Vector2 ( CosDeg ( lights [ i ] . LightSpotRadius1 ) , CosDeg ( lights [ i ] . LightSpotRadius2 ) ) ;
}
else graphics . Shaders . World3D . SpotLight = false ;
2017-07-26 15:35:22 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
model . Meshes [ j ] . DrawSubset ( 0 ) ;
}
}
}
//additive lights
if ( lightOffsets [ 2 ] > 0 )
{
count + = lightOffsets [ 2 ] ;
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . Add ) ;
for ( int i = lightOffsets [ 0 ] + lightOffsets [ 1 ] ; i < count ; i + + )
{
if ( BoundingBoxesIntersect ( t . BoundingBox , lights [ i ] . BoundingBox ) )
{
lpr = new Vector4 ( lights [ i ] . Center , lights [ i ] . LightRadius ) ;
if ( lpr . W = = 0 ) continue ;
graphics . Shaders . World3D . LightColor = lights [ i ] . LightColor ;
graphics . Shaders . World3D . LightPositionAndRadius = lpr ;
2018-02-04 02:18:59 +00:00
GZGeneral . LightData ld = lights [ i ] . LightType ;
if ( ld . LightType = = GZGeneral . LightType . SPOT )
{
graphics . Shaders . World3D . SpotLight = true ;
graphics . Shaders . World3D . LightOrientation = lights [ i ] . VectorLookAt ;
graphics . Shaders . World3D . Light2Radius = new Vector2 ( CosDeg ( lights [ i ] . LightSpotRadius1 ) , CosDeg ( lights [ i ] . LightSpotRadius2 ) ) ;
}
else graphics . Shaders . World3D . SpotLight = false ;
2017-07-26 15:35:22 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
model . Meshes [ j ] . DrawSubset ( 0 ) ;
}
}
}
//negative lights
if ( lightOffsets [ 3 ] > 0 )
{
count + = lightOffsets [ 3 ] ;
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . ReverseSubtract ) ;
for ( int i = lightOffsets [ 0 ] + lightOffsets [ 1 ] + lightOffsets [ 2 ] ; i < count ; i + + )
{
if ( BoundingBoxesIntersect ( t . BoundingBox , lights [ i ] . BoundingBox ) )
{
lpr = new Vector4 ( lights [ i ] . Center , lights [ i ] . LightRadius ) ;
if ( lpr . W = = 0 ) continue ;
Color4 lc = lights [ i ] . LightColor ;
graphics . Shaders . World3D . LightColor = new Color4 ( lc . Alpha , ( lc . Green + lc . Blue ) / 2 , ( lc . Red + lc . Blue ) / 2 , ( lc . Green + lc . Red ) / 2 ) ;
graphics . Shaders . World3D . LightPositionAndRadius = lpr ;
2018-02-04 02:18:59 +00:00
GZGeneral . LightData ld = lights [ i ] . LightType ;
if ( ld . LightType = = GZGeneral . LightType . SPOT )
{
graphics . Shaders . World3D . SpotLight = true ;
graphics . Shaders . World3D . LightOrientation = lights [ i ] . VectorLookAt ;
graphics . Shaders . World3D . Light2Radius = new Vector2 ( CosDeg ( lights [ i ] . LightSpotRadius1 ) , CosDeg ( lights [ i ] . LightSpotRadius2 ) ) ;
}
else graphics . Shaders . World3D . SpotLight = false ;
2017-07-26 15:35:22 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
model . Meshes [ j ] . DrawSubset ( 0 ) ;
}
}
}
}
}
2015-12-01 14:51:45 +00:00
}
2013-09-11 09:47:53 +00:00
graphics . Shaders . World3D . EndPass ( ) ;
2017-10-25 04:58:48 +00:00
if ( lightpass ) graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . Add ) ;
}
2013-09-11 09:47:53 +00:00
2016-01-11 13:00:52 +00:00
//mxd
private void RenderSky ( IEnumerable < VisualGeometry > geo )
{
VisualSector sector = null ;
// Set render settings
graphics . Shaders . World3D . BeginPass ( SHADERPASS_SKYBOX ) ;
graphics . Shaders . World3D . Texture1 = General . Map . Data . SkyBox ;
graphics . Shaders . World3D . World = world ;
graphics . Shaders . World3D . CameraPosition = new Vector4 ( cameraposition . x , cameraposition . y , cameraposition . z , 0f ) ;
foreach ( VisualGeometry g in geo )
{
// Changing sector?
if ( ! object . ReferenceEquals ( g . Sector , sector ) )
{
// Update the sector if needed
if ( g . Sector . NeedsUpdateGeo ) g . Sector . Update ( ) ;
// Only do this sector when a vertexbuffer is created
//mxd. No Map means that sector was deleted recently, I suppose
if ( g . Sector . GeometryBuffer ! = null & & g . Sector . Sector . Map ! = null )
{
// Change current sector
sector = g . Sector ;
// Set stream source
graphics . Device . SetStreamSource ( 0 , sector . GeometryBuffer , 0 , WorldVertex . Stride ) ;
}
else
{
sector = null ;
}
}
if ( sector ! = null )
{
// Set the colors to use
graphics . Shaders . World3D . HighlightColor = CalculateHighlightColor ( ( g = = highlighted ) & & showhighlight , ( g . Selected & & showselection ) ) ;
// Apply changes
graphics . Shaders . World3D . ApplySettings ( ) ;
// Render!
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , g . VertexOffset , g . Triangles ) ;
}
}
graphics . Shaders . World3D . EndPass ( ) ;
}
2018-02-04 02:18:59 +00:00
// [ZZ] this is copied from GZDoom
private float Smoothstep ( float edge0 , float edge1 , float x )
{
double t = Math . Min ( Math . Max ( ( x - edge0 ) / ( edge1 - edge0 ) , 0.0 ) , 1.0 ) ;
return ( float ) ( t * t * ( 3.0 - 2.0 * t ) ) ;
}
2013-09-11 09:47:53 +00:00
//mxd. This gets color from dynamic lights based on distance to thing.
//thing position must be in absolute cordinates
//(thing.Position.Z value is relative to floor of the sector the thing is in)
2014-12-03 23:15:26 +00:00
private Color4 GetLitColorForThing ( VisualThing t )
{
2013-09-11 09:47:53 +00:00
Color4 litColor = new Color4 ( ) ;
2015-12-01 14:51:45 +00:00
foreach ( VisualThing lt in lightthings )
2014-12-03 23:15:26 +00:00
{
2015-12-01 14:51:45 +00:00
// Don't light self
if ( General . Map . Data . GldefsEntries . ContainsKey ( t . Thing . Type ) & & General . Map . Data . GldefsEntries [ t . Thing . Type ] . DontLightSelf & & t . Thing . Index = = lt . Thing . Index )
2013-09-11 09:47:53 +00:00
continue ;
2018-02-04 02:18:59 +00:00
float distSquared = Vector3 . DistanceSquared ( lt . Center , t . Center ) ;
float radiusSquared = lt . LightRadius * lt . LightRadius ;
2015-09-27 21:09:14 +00:00
if ( distSquared < radiusSquared )
2014-12-03 23:15:26 +00:00
{
2018-02-04 02:18:59 +00:00
int sign = ( lt . LightType . LightRenderStyle = = GZGeneral . LightRenderStyle . SUBTRACTIVE ? - 1 : 1 ) ;
Vector3 L = ( t . Center - lt . Center ) ;
float dist = L . Length ( ) ;
float scaler = 1 - dist / lt . LightRadius * lt . LightColor . Alpha ;
if ( lt . LightType . LightType = = GZGeneral . LightType . SPOT )
{
Vector3 lookAt = lt . VectorLookAt ;
L . Normalize ( ) ;
float cosDir = Vector3 . Dot ( - L , lookAt ) ;
scaler * = ( float ) Smoothstep ( CosDeg ( lt . LightSpotRadius2 ) , CosDeg ( lt . LightSpotRadius1 ) , cosDir ) ;
}
if ( scaler > 0 )
{
litColor . Red + = lt . LightColor . Red * scaler * sign ;
litColor . Green + = lt . LightColor . Green * scaler * sign ;
litColor . Blue + = lt . LightColor . Blue * scaler * sign ;
}
2013-09-11 09:47:53 +00:00
}
}
2015-12-28 15:01:53 +00:00
2013-09-11 09:47:53 +00:00
return litColor ;
}
2009-05-05 21:13:50 +00:00
// This calculates the highlight/selection color
2014-12-03 23:15:26 +00:00
private Color4 CalculateHighlightColor ( bool ishighlighted , bool isselected )
2009-05-05 21:13:50 +00:00
{
2016-01-11 13:00:52 +00:00
if ( ! ishighlighted & & ! isselected ) return new Color4 ( ) ; //mxd
2009-05-05 21:13:50 +00:00
Color4 highlightcolor = isselected ? General . Colors . Selection . ToColorValue ( ) : General . Colors . Highlight . ToColorValue ( ) ;
highlightcolor . Alpha = ishighlighted ? highlightglowinv : highlightglow ;
return highlightcolor ;
}
2009-04-19 18:07:22 +00:00
// This finishes rendering
public void Finish ( )
{
2010-08-22 12:09:32 +00:00
General . Plugins . OnPresentDisplayBegin ( ) ;
2009-04-19 18:07:22 +00:00
// Done
graphics . FinishRendering ( ) ;
graphics . Present ( ) ;
highlighted = null ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Rendering
// This sets the highlighted object for the rendering
public void SetHighlightedObject ( IVisualPickable obj )
{
highlighted = obj ;
}
// This collects a visual sector's geometry for rendering
public void AddSectorGeometry ( VisualGeometry g )
{
2009-07-04 10:06:35 +00:00
// Must have a texture and vertices
2015-09-27 21:09:14 +00:00
if ( g . Texture ! = null & & g . Triangles > 0 )
2009-04-19 18:07:22 +00:00
{
2016-01-11 13:00:52 +00:00
if ( g . RenderAsSky & & General . Settings . GZDrawSky )
2009-04-19 18:07:22 +00:00
{
2016-01-11 13:00:52 +00:00
skygeo . Add ( g ) ;
}
else
{
switch ( g . RenderPass )
{
case RenderPass . Solid :
if ( ! solidgeo . ContainsKey ( g . Texture ) )
solidgeo . Add ( g . Texture , new List < VisualGeometry > ( ) ) ;
solidgeo [ g . Texture ] . Add ( g ) ;
break ;
case RenderPass . Mask :
if ( ! maskedgeo . ContainsKey ( g . Texture ) )
maskedgeo . Add ( g . Texture , new List < VisualGeometry > ( ) ) ;
maskedgeo [ g . Texture ] . Add ( g ) ;
break ;
case RenderPass . Additive :
case RenderPass . Alpha :
translucentgeo . Add ( g ) ;
break ;
default :
throw new NotImplementedException ( "Geometry rendering of " + g . RenderPass + " render pass is not implemented!" ) ;
}
2009-04-19 18:07:22 +00:00
}
}
}
// This collects a visual sector's geometry for rendering
public void AddThingGeometry ( VisualThing t )
{
2015-12-01 14:51:45 +00:00
//mxd. Gather lights
2018-02-03 20:31:34 +00:00
if ( General . Settings . GZDrawLightsMode ! = LightRenderMode . NONE & & ! fullbrightness & & t . LightType ! = null & & t . LightType . LightInternal )
2014-10-20 12:16:51 +00:00
{
2013-09-11 09:47:53 +00:00
t . UpdateLightRadius ( ) ;
2017-02-09 12:28:54 +00:00
if ( t . LightRadius > 0 )
2014-10-20 12:16:51 +00:00
{
2018-02-03 20:31:34 +00:00
if ( t . LightType ! = null & & t . LightType . LightAnimated )
2017-02-09 12:28:54 +00:00
t . UpdateBoundingBox ( ) ;
2015-09-27 21:09:14 +00:00
lightthings . Add ( t ) ;
2013-09-11 09:47:53 +00:00
}
}
2015-12-01 14:51:45 +00:00
//mxd. Gather models
2016-07-11 22:13:43 +00:00
if ( ( t . Thing . RenderMode = = ThingRenderMode . MODEL | | t . Thing . RenderMode = = ThingRenderMode . VOXEL ) & &
2015-06-29 08:15:07 +00:00
( General . Settings . GZDrawModelsMode = = ModelRenderMode . ALL | |
General . Settings . GZDrawModelsMode = = ModelRenderMode . ACTIVE_THINGS_FILTER | |
( General . Settings . GZDrawModelsMode = = ModelRenderMode . SELECTION & & t . Selected ) ) )
2014-10-20 12:16:51 +00:00
{
2017-07-26 16:34:01 +00:00
if ( t . RenderPass = = RenderPass . Mask | |
t . RenderPass = = RenderPass . Solid | |
( t . RenderPass = = RenderPass . Alpha & & ( t . VertexColor & 0xFF000000 ) = = 0xFF000000 ) )
{
ModelData mde = General . Map . Data . ModeldefEntries [ t . Thing . Type ] ;
if ( ! maskedmodelthings . ContainsKey ( mde ) ) maskedmodelthings . Add ( mde , new List < VisualThing > ( ) ) ;
maskedmodelthings [ mde ] . Add ( t ) ;
}
else if ( t . RenderPass = = RenderPass . Alpha | | t . RenderPass = = RenderPass . Additive )
{
translucentmodelthings . Add ( t ) ;
}
else
{
throw new NotImplementedException ( "Thing model rendering of " + t . RenderPass + " render pass is not implemented!" ) ;
}
2015-12-01 14:51:45 +00:00
}
// Gather regular things
2016-04-11 23:05:16 +00:00
else
2009-04-19 18:07:22 +00:00
{
2016-04-11 23:05:16 +00:00
//mxd. Set correct texture, geobuffer and triangles count
t . UpdateSpriteFrame ( ) ;
//Must have a texture!
if ( t . Texture ! = null )
2009-04-19 18:07:22 +00:00
{
2016-04-11 23:05:16 +00:00
//mxd
switch ( t . RenderPass )
{
case RenderPass . Solid :
if ( ! solidthings . ContainsKey ( t . Texture ) ) solidthings . Add ( t . Texture , new List < VisualThing > ( ) ) ;
solidthings [ t . Texture ] . Add ( t ) ;
break ;
2015-09-27 21:09:14 +00:00
2016-04-11 23:05:16 +00:00
case RenderPass . Mask :
if ( ! maskedthings . ContainsKey ( t . Texture ) ) maskedthings . Add ( t . Texture , new List < VisualThing > ( ) ) ;
maskedthings [ t . Texture ] . Add ( t ) ;
break ;
2015-09-27 21:09:14 +00:00
2016-04-11 23:05:16 +00:00
case RenderPass . Additive :
case RenderPass . Alpha :
translucentthings . Add ( t ) ;
break ;
2009-04-19 18:07:22 +00:00
2016-04-11 23:05:16 +00:00
default :
throw new NotImplementedException ( "Thing rendering of " + t . RenderPass + " render pass is not implemented!" ) ;
}
2015-09-27 21:09:14 +00:00
}
2009-04-19 18:07:22 +00:00
}
2015-12-01 14:51:45 +00:00
//mxd. Add to the plain list
allthings . Add ( t ) ;
2009-04-19 18:07:22 +00:00
}
2013-03-18 13:52:27 +00:00
//mxd
2015-10-02 14:47:34 +00:00
public void SetVisualVertices ( List < VisualVertex > verts ) { visualvertices = verts ; }
//mxd
public void SetEventLines ( List < Line3D > lines ) { eventlines = lines ; }
2013-03-18 13:52:27 +00:00
2013-09-11 09:47:53 +00:00
//mxd
2015-09-27 21:09:14 +00:00
private static bool BoundingBoxesIntersect ( Vector3D [ ] bbox1 , Vector3D [ ] bbox2 )
2014-10-20 12:16:51 +00:00
{
2015-09-27 21:09:14 +00:00
Vector3D dist = bbox1 [ 0 ] - bbox2 [ 0 ] ;
2013-09-11 09:47:53 +00:00
2015-09-27 21:09:14 +00:00
Vector3D halfSize1 = bbox1 [ 0 ] - bbox1 [ 1 ] ;
Vector3D halfSize2 = bbox2 [ 0 ] - bbox2 [ 1 ] ;
2013-09-11 09:47:53 +00:00
2015-09-27 21:09:14 +00:00
return ( halfSize1 . x + halfSize2 . x > = Math . Abs ( dist . x ) & & halfSize1 . y + halfSize2 . y > = Math . Abs ( dist . y ) & & halfSize1 . z + halfSize2 . z > = Math . Abs ( dist . z ) ) ;
2013-09-11 09:47:53 +00:00
}
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
// This renders the crosshair
public void RenderCrosshair ( )
{
2015-09-27 21:09:14 +00:00
//mxd
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
2009-04-19 18:07:22 +00:00
// Set renderstates
2013-09-11 09:47:53 +00:00
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . InverseSourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Device . SetTransform ( TransformState . World , Matrix . Identity ) ;
graphics . Device . SetTransform ( TransformState . Projection , Matrix . Identity ) ;
ApplyMatrices2D ( ) ;
2009-04-19 18:07:22 +00:00
2013-09-11 09:47:53 +00:00
// Texture
if ( crosshairbusy )
{
if ( General . Map . Data . CrosshairBusy3D . Texture = = null ) General . Map . Data . CrosshairBusy3D . CreateTexture ( ) ;
graphics . Shaders . Display2D . Texture1 = General . Map . Data . CrosshairBusy3D . Texture ;
}
else
{
if ( General . Map . Data . Crosshair3D . Texture = = null ) General . Map . Data . Crosshair3D . CreateTexture ( ) ;
graphics . Shaders . Display2D . Texture1 = General . Map . Data . Crosshair3D . Texture ;
}
2009-04-19 18:07:22 +00:00
2013-09-11 09:47:53 +00:00
// Draw
graphics . Shaders . Display2D . Begin ( ) ;
graphics . Shaders . Display2D . SetSettings ( 1.0f , 1.0f , 0.0f , 1.0f , true ) ;
graphics . Shaders . Display2D . BeginPass ( 1 ) ;
Added, Visual mode, GLDEFS, GLOOME: subtractive glow is now supported.
Changed, Visual mode: changed thing fog calculation logic. Should be closer to GZDoom now.
Fixed, GLDEFS parser: "height" texture parameter was not treated as optional.
Fixed, text lump parsers: in some cases incorrect line number was displayed in error and warning messages.
Fixed, Visual mode: glow effect was not applied to sectors with 3 sidedefs.
Fixed, Visual mode: in some cases glow effect was not updated when replacing textures.
Fixed, general interface: "Full Brightness" button state was not updated during map loading.
Fixed, Drag Linedefs/Vertices/Sectors/Things modes: positions of line length labels were not updated while panning the view.
Cosmetic: added a bunch of new icons.
Cosmetic: changed Visual mode crosshair.
2015-08-27 20:46:49 +00:00
graphics . Device . DrawUserPrimitives ( PrimitiveType . TriangleStrip , 0 , 2 , crosshairverts ) ;
2013-09-11 09:47:53 +00:00
graphics . Shaders . Display2D . EndPass ( ) ;
graphics . Shaders . Display2D . End ( ) ;
}
2009-04-19 18:07:22 +00:00
// This switches fog on and off
public void SetFogMode ( bool usefog )
{
graphics . Device . SetRenderState ( RenderState . FogEnable , usefog ) ;
}
// This siwtches crosshair busy icon on and off
public void SetCrosshairBusy ( bool busy )
{
crosshairbusy = busy ;
}
#endregion
}
}