using SharpDX.Direct3D11; using SharpDX.DXGI; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Device = SharpDX.Direct3D11.Device; using Buffer = SharpDX.Direct3D11.Buffer; using MapFlags = SharpDX.Direct3D11.MapFlags; using SharpDX; using CodeWalker.GameFiles; using CodeWalker.World; namespace CodeWalker.Rendering { public struct BasicShaderVSSceneVars { public Matrix ViewProj; public Vector4 WindVector; } public struct BasicShaderVSEntityVars { public Vector4 CamRel; public Quaternion Orientation; public uint HasSkeleton; public uint HasTransforms; public uint TintPaletteIndex; public uint Pad1; public Vector3 Scale; public uint IsInstanced; } public struct BasicShaderVSModelVars { public Matrix Transform; } public struct BasicShaderVSGeomVars { public uint EnableTint; public float TintYVal; public uint IsDecal; public uint EnableWind; public Vector4 WindOverrideParams; public Vector4 globalAnimUV0; public Vector4 globalAnimUV1; } public struct BasicShaderPSSceneVars { public ShaderGlobalLightParams GlobalLights; public uint EnableShadows; public uint RenderMode;//0=default, 1=normals, 2=tangents, 3=colours, 4=texcoords, 5=diffuse, 6=normalmap, 7=spec, 8=direct public uint RenderModeIndex; //colour/texcoord index public uint RenderSamplerCoord; //which texcoord to use in single texture mode } public struct BasicShaderPSGeomVars { public uint EnableTexture;//1+=diffuse1, 2+=diffuse2 public uint EnableTint; public uint EnableNormalMap; public uint EnableSpecMap; public uint EnableDetailMap; public uint IsDecal; public uint IsEmissive; public uint IsDistMap; public float bumpiness; public float AlphaScale; public float HardAlphaBlend; public float useTessellation; public Vector4 detailSettings; public Vector3 specMapIntMask; public float specularIntensityMult; public float specularFalloffMult; public float specularFresnel; public float wetnessMultiplier; public uint SpecOnly; public Vector4 TextureAlphaMask; } public struct BasicShaderInstGlobalMatrix { public Vector4 Row1; public Vector4 Row2; public Vector4 Row3; } public struct BasicShaderInstGlobals { public BasicShaderInstGlobalMatrix M0; public BasicShaderInstGlobalMatrix M1; public BasicShaderInstGlobalMatrix M2; public BasicShaderInstGlobalMatrix M3; public BasicShaderInstGlobalMatrix M4; public BasicShaderInstGlobalMatrix M5; public BasicShaderInstGlobalMatrix M6; public BasicShaderInstGlobalMatrix M7; } public struct BasicShaderInstLocals { public Vector3 vecBatchAabbMin; public float instPad0; public Vector3 vecBatchAabbDelta; public float instPad1; public Vector4 vecPlayerPos; public Vector2 _vecCollParams; public Vector2 instPad2; public Vector4 fadeAlphaDistUmTimer; public Vector4 uMovementParams; public Vector4 _fakedGrassNormal; public Vector3 gScaleRange; public float instPad3; public Vector4 gWindBendingGlobals; public Vector2 gWindBendScaleVar; public float gAlphaTest; public float gAlphaToCoverageScale; public Vector3 gLodFadeInstRange; public uint gUseComputeShaderOutputBuffer; } public class BasicShader : Shader, IDisposable { bool disposed = false; VertexShader basicvspnct; VertexShader basicvspnctt; VertexShader basicvspncttt; VertexShader basicvspncct; VertexShader basicvspncctt; VertexShader basicvspnccttt; VertexShader basicvspnctx; VertexShader basicvspncctx; VertexShader basicvspncttx; VertexShader basicvspnccttx; VertexShader basicvspnctttx; VertexShader basicvspncctttx; VertexShader basicvspbbnct; VertexShader basicvspbbnctx; VertexShader basicvspbbnctt; VertexShader basicvspbbncttt; VertexShader basicvspbbncct; VertexShader basicvspbbncctx; VertexShader basicvspbbnccttx; VertexShader basicvspbbncttx; VertexShader basicvsbox; VertexShader basicvssphere; VertexShader basicvscapsule; VertexShader basicvscylinder; PixelShader basicps; GpuVarsBuffer VSSceneVars; GpuVarsBuffer VSEntityVars; GpuVarsBuffer VSModelVars; GpuVarsBuffer VSGeomVars; GpuVarsBuffer PSSceneVars; GpuVarsBuffer PSGeomVars; GpuVarsBuffer InstGlobalVars; GpuVarsBuffer InstLocalVars; GpuABuffer BoneMatrices; SamplerState texsampler; SamplerState texsampleranis; SamplerState texsamplertnt; SamplerState texsamplertntyft; UnitCube cube; //for collision box render UnitSphere sphere; //for collision sphere render UnitCapsule capsule; //for collision capsule render UnitCylinder cylinder; //for collision cylinder render public bool AnisotropicFilter = false; public bool DecalMode = false; public float AlphaScale = 1.0f; public Vector4 WindVector = Vector4.Zero; public WorldRenderMode RenderMode = WorldRenderMode.Default; public int RenderVertexColourIndex = 1; public int RenderTextureCoordIndex = 1; public int RenderTextureSamplerCoord = 1; public ShaderParamNames RenderTextureSampler = ShaderParamNames.DiffuseSampler; public bool SpecularEnable = true; Matrix3_s[] defaultBoneMatrices; bool defaultBoneMatricesBound = false; private Dictionary layouts = new Dictionary(); public BasicShader(Device device) { byte[] vspnctbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCT.cso"); byte[] vspncttbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCTT.cso"); byte[] vspnctttbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCTTT.cso"); byte[] vspncctbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCT.cso"); byte[] vspnccttbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTT.cso"); byte[] vspncctttbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTTT.cso"); byte[] vspnctxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCTX.cso"); byte[] vspncctxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTX.cso"); byte[] vspncttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCTTX.cso"); byte[] vspnccttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTTX.cso"); byte[] vspnctttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCTTTX.cso"); byte[] vspncctttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTTTX.cso"); byte[] vspbbnctbytes = File.ReadAllBytes("Shaders\\BasicVS_PBBNCT.cso"); byte[] vspbbnctxbytes = File.ReadAllBytes("Shaders\\BasicVS_PBBNCTX.cso"); byte[] vspbbncttbytes = File.ReadAllBytes("Shaders\\BasicVS_PBBNCTT.cso"); byte[] vspbbnctttbytes = File.ReadAllBytes("Shaders\\BasicVS_PBBNCTTT.cso"); byte[] vspbbncctbytes = File.ReadAllBytes("Shaders\\BasicVS_PBBNCCT.cso"); byte[] vspbbncctxbytes = File.ReadAllBytes("Shaders\\BasicVS_PBBNCCTX.cso"); byte[] vspbbnccttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PBBNCCTTX.cso"); byte[] vspbbncttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PBBNCTTX.cso"); byte[] vsboxbytes = File.ReadAllBytes("Shaders\\BasicVS_Box.cso"); byte[] vsspherebytes = File.ReadAllBytes("Shaders\\BasicVS_Sphere.cso"); byte[] vscapsulebytes = File.ReadAllBytes("Shaders\\BasicVS_Capsule.cso"); byte[] vscylinderbytes = File.ReadAllBytes("Shaders\\BasicVS_Cylinder.cso"); byte[] psbytes = File.ReadAllBytes("Shaders\\BasicPS.cso"); basicvspnct = new VertexShader(device, vspnctbytes); basicvspnctt = new VertexShader(device, vspncttbytes); basicvspncttt = new VertexShader(device, vspnctttbytes); basicvspncct = new VertexShader(device, vspncctbytes); basicvspncctt = new VertexShader(device, vspnccttbytes); basicvspnccttt = new VertexShader(device, vspncctttbytes); basicvspnctx = new VertexShader(device, vspnctxbytes); basicvspncctx = new VertexShader(device, vspncctxbytes); basicvspncttx = new VertexShader(device, vspncttxbytes); basicvspnccttx = new VertexShader(device, vspnccttxbytes); basicvspnctttx = new VertexShader(device, vspnctttxbytes); basicvspncctttx = new VertexShader(device, vspncctttxbytes); basicvspbbnct = new VertexShader(device, vspbbnctbytes); basicvspbbnctx = new VertexShader(device, vspbbnctxbytes); basicvspbbnctt = new VertexShader(device, vspbbncttbytes); basicvspbbncttt = new VertexShader(device, vspbbnctttbytes); basicvspbbncct = new VertexShader(device, vspbbncctbytes); basicvspbbncctx = new VertexShader(device, vspbbncctxbytes); basicvspbbnccttx = new VertexShader(device, vspbbnccttxbytes); basicvspbbncttx = new VertexShader(device, vspbbncttxbytes); basicvsbox = new VertexShader(device, vsboxbytes); basicvssphere = new VertexShader(device, vsspherebytes); basicvscapsule = new VertexShader(device, vscapsulebytes); basicvscylinder = new VertexShader(device, vscylinderbytes); basicps = new PixelShader(device, psbytes); VSSceneVars = new GpuVarsBuffer(device); VSEntityVars = new GpuVarsBuffer(device); VSModelVars = new GpuVarsBuffer(device); VSGeomVars = new GpuVarsBuffer(device); PSSceneVars = new GpuVarsBuffer(device); PSGeomVars = new GpuVarsBuffer(device); InstGlobalVars = new GpuVarsBuffer(device); InstLocalVars = new GpuVarsBuffer(device); BoneMatrices = new GpuABuffer(device, 255); InitInstGlobalVars(); //supported layouts - requires Position, Normal, Colour, Texcoord layouts.Add(VertexType.Default, new InputLayout(device, vspnctbytes, VertexTypeGTAV.GetLayout(VertexType.Default))); layouts.Add(VertexType.PNCH2, new InputLayout(device, vspnctbytes, VertexTypeGTAV.GetLayout(VertexType.PNCH2, VertexDeclarationTypes.Types3)));//TODO? layouts.Add(VertexType.PNCTT, new InputLayout(device, vspncttbytes, VertexTypeGTAV.GetLayout(VertexType.PNCTT))); layouts.Add(VertexType.PNCTTT, new InputLayout(device, vspnctttbytes, VertexTypeGTAV.GetLayout(VertexType.PNCTTT))); layouts.Add(VertexType.PNCCT, new InputLayout(device, vspncctbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCT))); layouts.Add(VertexType.PNCCTT, new InputLayout(device, vspnccttbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCTT))); layouts.Add(VertexType.PNCCTTTT, new InputLayout(device, vspncctttbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCTTTT)));//TODO..? //normalmap layouts - requires Position, Normal, Colour, Texcoord, Tangent (X) layouts.Add(VertexType.DefaultEx, new InputLayout(device, vspnctxbytes, VertexTypeGTAV.GetLayout(VertexType.DefaultEx))); layouts.Add(VertexType.PCCH2H4, new InputLayout(device, vspnctxbytes, VertexTypeGTAV.GetLayout(VertexType.PCCH2H4, VertexDeclarationTypes.Types2))); layouts.Add(VertexType.PNCCTX, new InputLayout(device, vspncctxbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCTX))); layouts.Add(VertexType.PNCTTX, new InputLayout(device, vspncttxbytes, VertexTypeGTAV.GetLayout(VertexType.PNCTTX))); layouts.Add(VertexType.PNCCTTX, new InputLayout(device, vspnccttxbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCTTX))); layouts.Add(VertexType.PNCCTTX_2, new InputLayout(device, vspnccttxbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCTTX_2))); layouts.Add(VertexType.PNCTTTX, new InputLayout(device, vspnctttxbytes, VertexTypeGTAV.GetLayout(VertexType.PNCTTTX))); layouts.Add(VertexType.PNCTTTX_2, new InputLayout(device, vspnctttxbytes, VertexTypeGTAV.GetLayout(VertexType.PNCTTTX_2))); layouts.Add(VertexType.PNCTTTX_3, new InputLayout(device, vspnctttxbytes, VertexTypeGTAV.GetLayout(VertexType.PNCTTTX_3))); layouts.Add(VertexType.PNCTTTTX, new InputLayout(device, vspnctttxbytes, VertexTypeGTAV.GetLayout(VertexType.PNCTTTTX)));//TODO layouts.Add(VertexType.PNCCTTTX, new InputLayout(device, vspncctttxbytes, VertexTypeGTAV.GetLayout(VertexType.PNCCTTTX))); //skinned layouts layouts.Add(VertexType.PBBNCT, new InputLayout(device, vspbbnctbytes, VertexTypeGTAV.GetLayout(VertexType.PBBNCT))); layouts.Add(VertexType.PBBNCTX, new InputLayout(device, vspbbnctxbytes, VertexTypeGTAV.GetLayout(VertexType.PBBNCTX))); layouts.Add(VertexType.PBBNCTT, new InputLayout(device, vspbbncttbytes, VertexTypeGTAV.GetLayout(VertexType.PBBNCTT))); layouts.Add(VertexType.PBBNCTTT, new InputLayout(device, vspbbnctttbytes, VertexTypeGTAV.GetLayout(VertexType.PBBNCTTT))); layouts.Add(VertexType.PBBNCCT, new InputLayout(device, vspbbncctbytes, VertexTypeGTAV.GetLayout(VertexType.PBBNCCT))); layouts.Add(VertexType.PBBNCCTT, new InputLayout(device, vspbbncctbytes, VertexTypeGTAV.GetLayout(VertexType.PBBNCCTT)));//TODO layouts.Add(VertexType.PBBNCCTX, new InputLayout(device, vspbbncctxbytes, VertexTypeGTAV.GetLayout(VertexType.PBBNCCTX))); layouts.Add(VertexType.PBBNCTTX, new InputLayout(device, vspbbncttxbytes, VertexTypeGTAV.GetLayout(VertexType.PBBNCTTX))); layouts.Add(VertexType.PBBNCTTTX, new InputLayout(device, vspbbncttxbytes, VertexTypeGTAV.GetLayout(VertexType.PBBNCTTTX)));//TODO layouts.Add(VertexType.PBBNCCTTX, new InputLayout(device, vspbbnccttxbytes, VertexTypeGTAV.GetLayout(VertexType.PBBNCCTTX))); //PBBCCT todo //PBBNC todo texsampler = new SamplerState(device, new SamplerStateDescription() { AddressU = TextureAddressMode.Wrap, AddressV = TextureAddressMode.Wrap, AddressW = TextureAddressMode.Wrap, BorderColor = Color.Black, ComparisonFunction = Comparison.Always, Filter = Filter.MinMagMipLinear, MaximumAnisotropy = 1, MaximumLod = float.MaxValue, MinimumLod = 0, MipLodBias = 0, }); texsampleranis = new SamplerState(device, new SamplerStateDescription() { AddressU = TextureAddressMode.Wrap, AddressV = TextureAddressMode.Wrap, AddressW = TextureAddressMode.Wrap, BorderColor = Color.Black, ComparisonFunction = Comparison.Always, Filter = Filter.Anisotropic, MaximumAnisotropy = 8, MaximumLod = float.MaxValue, MinimumLod = 0, MipLodBias = 0, }); texsamplertnt = new SamplerState(device, new SamplerStateDescription() { AddressU = TextureAddressMode.Clamp, AddressV = TextureAddressMode.Wrap, AddressW = TextureAddressMode.Wrap, BorderColor = Color.White, ComparisonFunction = Comparison.Always, Filter = Filter.MinMagMipPoint, MaximumAnisotropy = 1, MaximumLod = float.MaxValue, MinimumLod = 0, MipLodBias = 0, }); texsamplertntyft = new SamplerState(device, new SamplerStateDescription() { AddressU = TextureAddressMode.Wrap, AddressV = TextureAddressMode.Wrap, AddressW = TextureAddressMode.Wrap, BorderColor = Color.White, ComparisonFunction = Comparison.Always, Filter = Filter.MinMagMipPoint, MaximumAnisotropy = 1, MaximumLod = float.MaxValue, MinimumLod = 0, MipLodBias = 0, }); cube = new UnitCube(device, vsboxbytes, false, false, true); sphere = new UnitSphere(device, vsspherebytes, 4); capsule = new UnitCapsule(device, vscapsulebytes, 4); cylinder = new UnitCylinder(device, vscylinderbytes, 8); defaultBoneMatrices = new Matrix3_s[255]; for (int i = 0; i < 255; i++) { defaultBoneMatrices[i].Row1 = Vector4.UnitX; defaultBoneMatrices[i].Row2 = Vector4.UnitY; defaultBoneMatrices[i].Row3 = Vector4.UnitZ; } } private void InitInstGlobalVars() { var m0 = Matrix3x3.RotationZ(0.00f * (float)Math.PI); var m1 = Matrix3x3.RotationZ(0.25f * (float)Math.PI); var m2 = Matrix3x3.RotationZ(0.50f * (float)Math.PI); var m3 = Matrix3x3.RotationZ(0.75f * (float)Math.PI); var m4 = Matrix3x3.RotationZ(1.00f * (float)Math.PI); var m5 = Matrix3x3.RotationZ(1.25f * (float)Math.PI); var m6 = Matrix3x3.RotationZ(1.50f * (float)Math.PI); var m7 = Matrix3x3.RotationZ(1.75f * (float)Math.PI); InstGlobalVars.Vars.M0.Row1 = new Vector4(m0.Row1, 1); InstGlobalVars.Vars.M0.Row2 = new Vector4(m0.Row2, 1); InstGlobalVars.Vars.M0.Row3 = new Vector4(m0.Row3, 1); InstGlobalVars.Vars.M1.Row1 = new Vector4(m1.Row1, 1); InstGlobalVars.Vars.M1.Row2 = new Vector4(m1.Row2, 1); InstGlobalVars.Vars.M1.Row3 = new Vector4(m1.Row3, 1); InstGlobalVars.Vars.M2.Row1 = new Vector4(m2.Row1, 1); InstGlobalVars.Vars.M2.Row2 = new Vector4(m2.Row2, 1); InstGlobalVars.Vars.M2.Row3 = new Vector4(m2.Row3, 1); InstGlobalVars.Vars.M3.Row1 = new Vector4(m3.Row1, 1); InstGlobalVars.Vars.M3.Row2 = new Vector4(m3.Row2, 1); InstGlobalVars.Vars.M3.Row3 = new Vector4(m3.Row3, 1); InstGlobalVars.Vars.M4.Row1 = new Vector4(m4.Row1, 1); InstGlobalVars.Vars.M4.Row2 = new Vector4(m4.Row2, 1); InstGlobalVars.Vars.M4.Row3 = new Vector4(m4.Row3, 1); InstGlobalVars.Vars.M5.Row1 = new Vector4(m5.Row1, 1); InstGlobalVars.Vars.M5.Row2 = new Vector4(m5.Row2, 1); InstGlobalVars.Vars.M5.Row3 = new Vector4(m5.Row3, 1); InstGlobalVars.Vars.M6.Row1 = new Vector4(m6.Row1, 1); InstGlobalVars.Vars.M6.Row2 = new Vector4(m6.Row2, 1); InstGlobalVars.Vars.M6.Row3 = new Vector4(m6.Row3, 1); InstGlobalVars.Vars.M7.Row1 = new Vector4(m7.Row1, 1); InstGlobalVars.Vars.M7.Row2 = new Vector4(m7.Row2, 1); InstGlobalVars.Vars.M7.Row3 = new Vector4(m7.Row3, 1); } private void SetVertexShader(DeviceContext context, VertexType type) { VertexShader vs = basicvspnct; switch (type) { case VertexType.Default: case VertexType.PNCH2: vs = basicvspnct; break; case VertexType.PNCTT: vs = basicvspnctt; break; case VertexType.PNCTTT: vs = basicvspncttt; break; case VertexType.PNCCT: vs = basicvspncct; break; case VertexType.PNCCTT://not used? vs = basicvspncctt; break; case VertexType.PNCCTTTT://not used? vs = basicvspnccttt; break; case VertexType.DefaultEx: case VertexType.PCCH2H4: vs = basicvspnctx; break; case VertexType.PNCCTX: vs = basicvspncctx; break; case VertexType.PNCTTX: vs = basicvspncttx; break; case VertexType.PNCCTTX://not used? case VertexType.PNCCTTX_2://not used? vs = basicvspnccttx; break; case VertexType.PNCTTTX: case VertexType.PNCTTTX_2: case VertexType.PNCTTTX_3: case VertexType.PNCTTTTX: //not using last texcoords! vs = basicvspnctttx; break; case VertexType.PNCCTTTX://not used? vs = basicvspncctttx; break; case VertexType.PBBNCT: vs = basicvspbbnct; break; case VertexType.PBBNCTT: vs = basicvspbbnctt; break; case VertexType.PBBNCTTT: vs = basicvspbbncttt; break; case VertexType.PBBNCCT: vs = basicvspbbncct; break; case VertexType.PBBNCCTT://todo vs = basicvspbbncct; break; case VertexType.PBBNCTX: vs = basicvspbbnctx; break; case VertexType.PBBNCCTX: vs = basicvspbbncctx; break; case VertexType.PBBNCTTX: vs = basicvspbbncttx; break; case VertexType.PBBNCCTTX: vs = basicvspbbnccttx; break; case VertexType.PBBNCTTTX: vs = basicvspbbncttx;//TODO break; default: break; } context.VertexShader.Set(vs); } public override void SetShader(DeviceContext context) { context.PixelShader.Set(basicps); } public override bool SetInputLayout(DeviceContext context, VertexType type) { InputLayout l; if (layouts.TryGetValue(type, out l)) { SetVertexShader(context, type); context.InputAssembler.InputLayout = l; return true; } return false; } public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights) { uint rendermode = 0; uint rendermodeind = 1; SpecularEnable = lights.SpecularEnabled; switch (RenderMode) { case WorldRenderMode.VertexNormals: rendermode = 1; break; case WorldRenderMode.VertexTangents: rendermode = 2; break; case WorldRenderMode.VertexColour: rendermode = 3; rendermodeind = (uint)RenderVertexColourIndex; break; case WorldRenderMode.TextureCoord: rendermode = 4; rendermodeind = (uint)RenderTextureCoordIndex; break; case WorldRenderMode.SingleTexture: rendermode = 8;//direct mode break; } VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix); VSSceneVars.Vars.WindVector = WindVector; VSSceneVars.Update(context); VSSceneVars.SetVSCBuffer(context, 0); PSSceneVars.Vars.GlobalLights = lights.Params; PSSceneVars.Vars.EnableShadows = (shadowmap != null) ? 1u : 0u; PSSceneVars.Vars.RenderMode = rendermode; PSSceneVars.Vars.RenderModeIndex = rendermodeind; PSSceneVars.Vars.RenderSamplerCoord = (uint)RenderTextureSamplerCoord; PSSceneVars.Update(context); PSSceneVars.SetPSCBuffer(context, 0); if (shadowmap != null) { shadowmap.SetFinalRenderResources(context); } if (!InstGlobalVars.Flag) //on the first frame, update the instance globals { InstGlobalVars.Update(context); InstGlobalVars.Flag = true; } } public override void SetEntityVars(DeviceContext context, ref RenderableInst rend) { VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f); VSEntityVars.Vars.Orientation = rend.Orientation; VSEntityVars.Vars.Scale = rend.Scale; VSEntityVars.Vars.HasSkeleton = rend.Renderable.HasSkeleton ? 1u : 0; VSEntityVars.Vars.HasTransforms = rend.Renderable.HasTransforms ? 1u : 0; VSEntityVars.Vars.TintPaletteIndex = rend.TintPaletteIndex; VSEntityVars.Vars.IsInstanced = 0; VSEntityVars.Update(context); VSEntityVars.SetVSCBuffer(context, 2); } public override void SetModelVars(DeviceContext context, RenderableModel model) { if (model.Owner.Skeleton?.BoneTransforms != null) { SetBoneMatrices(context, model.Owner.Skeleton.BoneTransforms); defaultBoneMatricesBound = false; } else if (!defaultBoneMatricesBound) { SetBoneMatrices(context, defaultBoneMatrices); defaultBoneMatricesBound = true; } if (!model.UseTransform) return; VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform); VSModelVars.Update(context); VSModelVars.SetVSCBuffer(context, 3); } public override void SetGeomVars(DeviceContext context, RenderableGeometry geom) { RenderableTexture texture = null; RenderableTexture texture2 = null; RenderableTexture tintpal = null; RenderableTexture bumptex = null; RenderableTexture spectex = null; RenderableTexture detltex = null; bool isdistmap = false; float tntpalind = 0.0f; if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0)) { if (RenderMode == WorldRenderMode.Default) { for (int i = 0; i < geom.RenderableTextures.Length; i++) { var itex = geom.RenderableTextures[i]; if (geom.HDTextureEnable) { var hdtex = geom.RenderableTexturesHD[i]; if ((hdtex != null) && (hdtex.IsLoaded)) { itex = hdtex; } } var ihash = geom.TextureParamHashes[i]; if (itex == null) continue; if (itex.Key?.NameHash == 1678728908 /*"blank"*/) continue; switch (ihash) { case ShaderParamNames.DiffuseSampler: case ShaderParamNames.PlateBgSampler: texture = itex; break; case ShaderParamNames.BumpSampler: case ShaderParamNames.PlateBgBumpSampler: bumptex = itex; break; case ShaderParamNames.SpecSampler: spectex = itex; break; case ShaderParamNames.DetailSampler: detltex = itex; break; case ShaderParamNames.TintPaletteSampler: case ShaderParamNames.TextureSamplerDiffPal: tintpal = itex; if (tintpal.Key != null) { //this is slightly dodgy but VSEntityVars should have the correct value in it... tntpalind = (VSEntityVars.Vars.TintPaletteIndex + 0.5f) / tintpal.Key.Height; } break; case ShaderParamNames.distanceMapSampler: texture = itex; isdistmap = true; break; case ShaderParamNames.DiffuseSampler2: case ShaderParamNames.DiffuseExtraSampler: texture2 = itex; break; case ShaderParamNames.heightSampler: case ShaderParamNames.EnvironmentSampler: //case MetaName.SnowSampler0: //case MetaName.SnowSampler1: //case MetaName.DiffuseSampler3: //case MetaName.DirtSampler: //case MetaName.DirtBumpSampler: break; case ShaderParamNames.FlowSampler: case ShaderParamNames.FogSampler: case ShaderParamNames.FoamSampler: if (texture == null) texture = itex; break; default: if (texture == null) texture = itex; break; } } } else if (RenderMode == WorldRenderMode.SingleTexture) { for (int i = 0; i < geom.RenderableTextures.Length; i++) { var itex = geom.RenderableTextures[i]; var ihash = geom.TextureParamHashes[i]; if (ihash == RenderTextureSampler) { texture = itex; break; } } } } bool usediff = ((texture != null) && (texture.ShaderResourceView != null)); bool usediff2 = ((texture2 != null) && (texture2.ShaderResourceView != null)); bool usebump = ((bumptex != null) && (bumptex.ShaderResourceView != null)); bool usespec = ((spectex != null) && (spectex.ShaderResourceView != null)); bool usedetl = ((detltex != null) && (detltex.ShaderResourceView != null)); bool usetint = ((tintpal != null) && (tintpal.ShaderResourceView != null)); uint tintflag = 0; if (usetint) tintflag = 1; Vector4 textureAlphaMask = Vector4.Zero; uint decalflag = DecalMode ? 1u : 0u; uint windflag = geom.EnableWind ? 1u : 0u; uint emflag = geom.IsEmissive ? 1u : 0u; uint pstintflag = tintflag; var shaderName = geom.DrawableGeom.Shader.Name; var shaderFile = geom.DrawableGeom.Shader.FileName; switch (shaderFile.Hash) { case 2245870123: //trees_normal_diffspec_tnt.sps case 3334613197: //trees_tnt.sps case 1229591973://{trees_normal_spec_tnt.sps} if (usetint) tintflag = 2; //use 2nd vertex colour channel for tint... break; case 3267631682: //weapon_normal_spec_detail_tnt.sps case 14185869: //weapon_normal_spec_tnt.sps break; //regular tinting? case 231364109: //weapon_normal_spec_cutout_palette.sps case 3294641629://weapon_normal_spec_detail_palette.sps case 731050667: //weapon_normal_spec_palette.sps if (usetint) { tintflag = 0; pstintflag = 2; } //use diffuse sampler alpha for tint lookup! break; case 3880384844://{decal_spec_only.sps}w case 600733812://{decal_amb_only.sps} case 2842248626://{spec_decal.sps} case 2457676400://{reflect_decal.sps} case 2706821972://{mirror_decal.sps} //if (RenderMode == WorldRenderMode.Default) usediff = false; break; case 2655725442://{decal_dirt.sps} textureAlphaMask = geom.DirtDecalMask; decalflag = 2; break; } if (VSEntityVars.Vars.IsInstanced>0) { pstintflag = 1; switch (shaderFile.Hash) { case 916743331: //{grass_batch.sps} windflag = 1; break; case 3833671083://{normal_spec_batch.sps} windflag = 0; break; default: break; } } PSGeomVars.Vars.EnableTexture = (usediff ? 1u : 0u) + (usediff2 ? 2u : 0u); PSGeomVars.Vars.EnableTint = pstintflag; PSGeomVars.Vars.EnableNormalMap = usebump ? 1u : 0u; PSGeomVars.Vars.EnableSpecMap = usespec ? 1u : 0u; PSGeomVars.Vars.EnableDetailMap = usedetl ? 1u : 0u; PSGeomVars.Vars.IsDecal = decalflag; PSGeomVars.Vars.IsEmissive = emflag; PSGeomVars.Vars.IsDistMap = isdistmap ? 1u : 0u; PSGeomVars.Vars.bumpiness = geom.bumpiness; PSGeomVars.Vars.AlphaScale = isdistmap ? 1.0f : AlphaScale; PSGeomVars.Vars.HardAlphaBlend = 0.0f; //todo: cutouts flag! PSGeomVars.Vars.useTessellation = 0.0f; PSGeomVars.Vars.detailSettings = geom.detailSettings; PSGeomVars.Vars.specMapIntMask = geom.specMapIntMask; PSGeomVars.Vars.specularIntensityMult = SpecularEnable ? geom.specularIntensityMult : 0.0f; PSGeomVars.Vars.specularFalloffMult = geom.specularFalloffMult; PSGeomVars.Vars.specularFresnel = geom.specularFresnel; PSGeomVars.Vars.wetnessMultiplier = geom.wetnessMultiplier; PSGeomVars.Vars.SpecOnly = geom.SpecOnly ? 1u : 0u; PSGeomVars.Vars.TextureAlphaMask = textureAlphaMask; PSGeomVars.Update(context); PSGeomVars.SetPSCBuffer(context, 2); VSGeomVars.Vars.EnableTint = tintflag; VSGeomVars.Vars.TintYVal = tntpalind; VSGeomVars.Vars.IsDecal = DecalMode ? 1u : 0u; VSGeomVars.Vars.EnableWind = windflag; VSGeomVars.Vars.WindOverrideParams = geom.WindOverrideParams; VSGeomVars.Vars.globalAnimUV0 = geom.globalAnimUV0; VSGeomVars.Vars.globalAnimUV1 = geom.globalAnimUV1; VSGeomVars.Update(context); VSGeomVars.SetVSCBuffer(context, 4); context.VertexShader.SetSampler(0, geom.IsFragment ? texsamplertntyft : texsamplertnt); context.PixelShader.SetSampler(0, AnisotropicFilter ? texsampleranis : texsampler); if (usediff) { texture.SetPSResource(context, 0); } if (usebump) { bumptex.SetPSResource(context, 2); } if (usespec) { spectex.SetPSResource(context, 3); } if (usedetl) { detltex.SetPSResource(context, 4); } if (usediff2) { texture2.SetPSResource(context, 5); } if (usetint) { tintpal.SetVSResource(context, 0); } if (pstintflag == 2) { tintpal.SetPSResource(context, 6); } if (geom.BoneTransforms != null) { SetBoneMatrices(context, geom.BoneTransforms); defaultBoneMatricesBound = false; } } public void SetBoneMatrices(DeviceContext context, Matrix3_s[] matrices) { BoneMatrices.Update(context, matrices); BoneMatrices.SetVSCBuffer(context, 7); } public void SetInstanceVars(DeviceContext context, RenderableInstanceBatch batch) { var gb = batch.Key; // sanity check if (batch.GrassInstanceBuffer == null) return; VSEntityVars.Vars.CamRel = new Vector4(batch.CamRel, 0.0f); VSEntityVars.Vars.Orientation = Quaternion.Identity; VSEntityVars.Vars.Scale = Vector3.One; VSEntityVars.Vars.HasSkeleton = 0; VSEntityVars.Vars.HasTransforms = 0; VSEntityVars.Vars.TintPaletteIndex = 0; VSEntityVars.Vars.IsInstanced = 1; VSEntityVars.Update(context); VSEntityVars.SetVSCBuffer(context, 2); InstGlobalVars.SetVSCBuffer(context, 5); InstLocalVars.Vars.vecBatchAabbMin = batch.AABBMin; InstLocalVars.Vars.vecBatchAabbDelta = batch.AABBMax - batch.AABBMin; InstLocalVars.Vars.vecPlayerPos = new Vector4(batch.Position - batch.CamRel, 1.0f); InstLocalVars.Vars._vecCollParams = new Vector2(2.0f, -3.0f);//range, offset InstLocalVars.Vars.fadeAlphaDistUmTimer = new Vector4(0.0f); InstLocalVars.Vars.uMovementParams = new Vector4(0.0f); InstLocalVars.Vars._fakedGrassNormal = new Vector4(Vector3.Normalize(-batch.CamRel), 0.0f); InstLocalVars.Vars.gScaleRange = gb.Batch.ScaleRange; InstLocalVars.Vars.gWindBendingGlobals = new Vector4(WindVector.X, WindVector.Y, 1.0f, 1.0f); InstLocalVars.Vars.gWindBendScaleVar = new Vector2(WindVector.Z, WindVector.W); InstLocalVars.Vars.gAlphaTest = 0.0f; InstLocalVars.Vars.gAlphaToCoverageScale = 1.0f; InstLocalVars.Vars.gLodFadeInstRange = new Vector3(gb.Batch.LodInstFadeRange, gb.Batch.LodFadeStartDist, gb.Batch.lodDist); InstLocalVars.Vars.gUseComputeShaderOutputBuffer = 0; InstLocalVars.Update(context); InstLocalVars.SetVSCBuffer(context, 6); context.VertexShader.SetShaderResource(2, batch.GrassInstanceBuffer.SRV); } public void RenderBoundGeom(DeviceContext context, RenderableBoundGeometryInst inst) { VSEntityVars.Vars.CamRel = new Vector4(inst.Inst.CamRel, 0.0f); VSEntityVars.Vars.Orientation = inst.Inst.Orientation; VSEntityVars.Vars.Scale = inst.Inst.Scale; VSEntityVars.Vars.HasSkeleton = 0; VSEntityVars.Vars.HasTransforms = 0; //todo! bounds transforms..? VSEntityVars.Vars.TintPaletteIndex = 0; VSEntityVars.Vars.IsInstanced = 0; VSEntityVars.Update(context); VSEntityVars.SetVSCBuffer(context, 2); PSGeomVars.Vars.EnableTexture = 0; PSGeomVars.Vars.EnableTint = 0; PSGeomVars.Vars.EnableNormalMap = 0; PSGeomVars.Vars.EnableSpecMap = 0; PSGeomVars.Vars.EnableDetailMap = 0; PSGeomVars.Vars.IsDecal = 0; PSGeomVars.Vars.IsEmissive = 0; PSGeomVars.Vars.IsDistMap = 0; PSGeomVars.Vars.bumpiness = 0; PSGeomVars.Vars.AlphaScale = 1; PSGeomVars.Vars.HardAlphaBlend = 0; PSGeomVars.Vars.useTessellation = 0; PSGeomVars.Vars.detailSettings = Vector4.Zero; PSGeomVars.Vars.specMapIntMask = Vector3.Zero; PSGeomVars.Vars.specularIntensityMult = 1.0f; PSGeomVars.Vars.specularFalloffMult = 1.0f; PSGeomVars.Vars.specularFresnel = 1.0f; PSGeomVars.Vars.wetnessMultiplier = 0.0f; PSGeomVars.Vars.SpecOnly = 0; PSGeomVars.Vars.TextureAlphaMask = Vector4.Zero; PSGeomVars.Update(context); PSGeomVars.SetPSCBuffer(context, 2); VSGeomVars.Vars.EnableTint = 0; VSGeomVars.Vars.TintYVal = 0.0f; VSGeomVars.Vars.IsDecal = 0; VSGeomVars.Vars.EnableWind = 0; VSGeomVars.Vars.WindOverrideParams = Vector4.Zero; VSGeomVars.Vars.globalAnimUV0 = new Vector4(1.0f, 0.0f, 0.0f, 0.0f); VSGeomVars.Vars.globalAnimUV1 = new Vector4(0.0f, 1.0f, 0.0f, 0.0f); VSGeomVars.Update(context); VSGeomVars.SetVSCBuffer(context, 4); if (inst.Geom.VertexBuffer != null) //render the triangles { SetVertexShader(context, VertexType.Default); SetInputLayout(context, VertexType.Default); inst.Geom.RenderTriangles(context); } //render the boxes if (inst.Geom.BoxBuffer != null) { context.VertexShader.Set(basicvsbox); context.VertexShader.SetShaderResource(1, inst.Geom.BoxBuffer.SRV); cube.DrawInstanced(context, inst.Geom.BoxBuffer.StructCount); } //render the spheres if (inst.Geom.SphereBuffer != null) { context.VertexShader.Set(basicvssphere); context.VertexShader.SetShaderResource(1, inst.Geom.SphereBuffer.SRV); sphere.DrawInstanced(context, inst.Geom.SphereBuffer.StructCount); } //render the capsules if (inst.Geom.CapsuleBuffer != null) { context.VertexShader.Set(basicvscapsule); context.VertexShader.SetShaderResource(1, inst.Geom.CapsuleBuffer.SRV); capsule.DrawInstanced(context, inst.Geom.CapsuleBuffer.StructCount); } //render the cylinders if (inst.Geom.CylinderBuffer != null) { context.VertexShader.Set(basicvscylinder); context.VertexShader.SetShaderResource(1, inst.Geom.CylinderBuffer.SRV); cylinder.DrawInstanced(context, inst.Geom.CylinderBuffer.StructCount); } } public override void UnbindResources(DeviceContext context) { context.VertexShader.SetConstantBuffer(0, null); context.PixelShader.SetConstantBuffer(0, null); context.VertexShader.SetConstantBuffer(1, null); //shadowmap context.PixelShader.SetConstantBuffer(1, null); //shadowmap context.PixelShader.SetShaderResource(1, null);//shadowmap context.PixelShader.SetSampler(1, null); //shadowmap context.VertexShader.SetConstantBuffer(2, null); context.VertexShader.SetConstantBuffer(3, null); context.PixelShader.SetConstantBuffer(2, null); context.VertexShader.SetConstantBuffer(4, null); context.VertexShader.SetConstantBuffer(5, null); context.VertexShader.SetConstantBuffer(6, null); context.VertexShader.SetSampler(0, null); context.PixelShader.SetSampler(0, null); context.PixelShader.SetShaderResource(0, null); context.PixelShader.SetShaderResource(2, null); context.PixelShader.SetShaderResource(3, null); context.PixelShader.SetShaderResource(4, null); context.PixelShader.SetShaderResource(5, null); context.VertexShader.SetShaderResource(0, null); context.VertexShader.SetShaderResource(1, null); context.VertexShader.SetShaderResource(2, null); context.VertexShader.Set(null); context.PixelShader.Set(null); } public void Dispose() { if (disposed) return; cube.Dispose(); sphere.Dispose(); capsule.Dispose(); cylinder.Dispose(); texsampler.Dispose(); texsampleranis.Dispose(); texsamplertnt.Dispose(); foreach (InputLayout layout in layouts.Values) { layout.Dispose(); } layouts.Clear(); VSSceneVars.Dispose(); VSEntityVars.Dispose(); VSModelVars.Dispose(); VSGeomVars.Dispose(); PSSceneVars.Dispose(); PSGeomVars.Dispose(); InstGlobalVars.Dispose(); InstLocalVars.Dispose(); BoneMatrices.Dispose(); basicps.Dispose(); basicvspnct.Dispose(); basicvspnctt.Dispose(); basicvspncttt.Dispose(); basicvspncct.Dispose(); basicvspncctt.Dispose(); basicvspnccttt.Dispose(); basicvspnctx.Dispose(); basicvspncctx.Dispose(); basicvspncttx.Dispose(); basicvspnccttx.Dispose(); basicvspnctttx.Dispose(); basicvspncctttx.Dispose(); basicvspbbnct.Dispose(); basicvspbbnctx.Dispose(); basicvspbbnctt.Dispose(); basicvspbbncttt.Dispose(); basicvspbbncct.Dispose(); basicvspbbncctx.Dispose(); basicvspbbnccttx.Dispose(); basicvspbbncttx.Dispose(); basicvsbox.Dispose(); basicvssphere.Dispose(); basicvscapsule.Dispose(); basicvscylinder.Dispose(); disposed = true; } } }