From 7b18fa2035b1bd76bce52309b8b1c0de151fa52d Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 21 Nov 2015 17:25:46 +0100 Subject: [PATCH] xrRenderGL: Add OpenGL renderer from X-Ray 1.5. --- src/Layers/xrRenderGL/glBufferUtils.cpp | 282 +++++ src/Layers/xrRenderGL/glBufferUtils.h | 16 + src/Layers/xrRenderGL/glDetailManager_VS.cpp | 225 ++++ src/Layers/xrRenderGL/glR_Backend_Runtime.h | 318 +++++ src/Layers/xrRenderGL/glSH_RT.cpp | 76 ++ src/Layers/xrRenderGL/glSH_Texture.cpp | 336 +++++ src/Layers/xrRenderGL/glState.cpp | 246 ++++ src/Layers/xrRenderGL/glState.h | 55 + src/Layers/xrRenderGL/glStateUtils.cpp | 189 +++ src/Layers/xrRenderGL/glStateUtils.h | 16 + src/Layers/xrRenderGL/glTextureUtils.cpp | 112 ++ src/Layers/xrRenderGL/glTextureUtils.h | 10 + src/Layers/xrRenderGL/glr_constants_cache.h | 153 +++ src/Layers/xrRenderPC_GL/GLUtils.cpp | 4 + src/Layers/xrRenderPC_GL/GLUtils.h | 66 + src/Layers/xrRenderPC_GL/GL_DStreams.cpp | 192 +++ src/Layers/xrRenderPC_GL/SMAP_Allocator.h | 85 ++ .../xrRenderPC_GL/blender_bloom_build.cpp | 41 + .../xrRenderPC_GL/blender_bloom_build.h | 14 + src/Layers/xrRenderPC_GL/blender_combine.cpp | 72 ++ src/Layers/xrRenderPC_GL/blender_combine.h | 14 + .../xrRenderPC_GL/blender_deffer_aref.cpp | 80 ++ .../xrRenderPC_GL/blender_deffer_aref.h | 21 + .../xrRenderPC_GL/blender_deffer_flat.cpp | 39 + .../xrRenderPC_GL/blender_deffer_flat.h | 17 + .../xrRenderPC_GL/blender_deffer_model.cpp | 94 ++ .../xrRenderPC_GL/blender_deffer_model.h | 19 + .../xrRenderPC_GL/blender_light_direct.cpp | 52 + .../xrRenderPC_GL/blender_light_direct.h | 14 + .../xrRenderPC_GL/blender_light_mask.cpp | 46 + src/Layers/xrRenderPC_GL/blender_light_mask.h | 14 + .../xrRenderPC_GL/blender_light_occq.cpp | 24 + src/Layers/xrRenderPC_GL/blender_light_occq.h | 14 + .../xrRenderPC_GL/blender_light_point.cpp | 67 + .../xrRenderPC_GL/blender_light_point.h | 14 + .../xrRenderPC_GL/blender_light_reflected.cpp | 21 + .../xrRenderPC_GL/blender_light_reflected.h | 14 + .../xrRenderPC_GL/blender_light_spot.cpp | 68 + src/Layers/xrRenderPC_GL/blender_light_spot.h | 14 + .../xrRenderPC_GL/blender_luminance.cpp | 32 + src/Layers/xrRenderPC_GL/blender_luminance.h | 14 + src/Layers/xrRenderPC_GL/blender_ssao.cpp | 32 + src/Layers/xrRenderPC_GL/blender_ssao.h | 14 + .../xrRenderPC_GL/glApplicationRender.cpp | 270 ++++ .../xrRenderPC_GL/glApplicationRender.h | 26 + src/Layers/xrRenderPC_GL/glDebugRender.cpp | 17 + src/Layers/xrRenderPC_GL/glDebugRender.h | 36 + .../xrRenderPC_GL/glEnvironmentRender.cpp | 311 +++++ .../xrRenderPC_GL/glEnvironmentRender.h | 82 ++ src/Layers/xrRenderPC_GL/glFontRender.cpp | 149 +++ src/Layers/xrRenderPC_GL/glFontRender.h | 18 + .../xrRenderPC_GL/glLensFlareRender.cpp | 125 ++ src/Layers/xrRenderPC_GL/glLensFlareRender.h | 31 + .../xrRenderPC_GL/glObjectSpaceRender.cpp | 61 + .../xrRenderPC_GL/glObjectSpaceRender.h | 24 + src/Layers/xrRenderPC_GL/glRainRender.cpp | 261 ++++ src/Layers/xrRenderPC_GL/glRainRender.h | 26 + .../xrRenderPC_GL/glRenderDeviceRender.cpp | 466 +++++++ .../xrRenderPC_GL/glRenderDeviceRender.h | 82 ++ src/Layers/xrRenderPC_GL/glRenderFactory.cpp | 74 ++ src/Layers/xrRenderPC_GL/glRenderFactory.h | 38 + .../glResourceManager_Resources.cpp | 627 +++++++++ .../glResourceManager_Scripting.cpp | 356 ++++++ src/Layers/xrRenderPC_GL/glStatsRender.cpp | 64 + src/Layers/xrRenderPC_GL/glStatsRender.h | 19 + src/Layers/xrRenderPC_GL/glTexture.cpp | 190 +++ .../xrRenderPC_GL/glThunderboltDescRender.cpp | 20 + .../xrRenderPC_GL/glThunderboltDescRender.h | 19 + .../xrRenderPC_GL/glThunderboltRender.cpp | 111 ++ .../xrRenderPC_GL/glThunderboltRender.h | 18 + src/Layers/xrRenderPC_GL/glUIRender.cpp | 279 ++++ src/Layers/xrRenderPC_GL/glUIRender.h | 59 + .../xrRenderPC_GL/glUISequenceVideoItem.cpp | 17 + .../xrRenderPC_GL/glUISequenceVideoItem.h | 22 + src/Layers/xrRenderPC_GL/glUIShader.cpp | 17 + src/Layers/xrRenderPC_GL/glUIShader.h | 19 + src/Layers/xrRenderPC_GL/glWallMarkArray.cpp | 46 + src/Layers/xrRenderPC_GL/glWallMarkArray.h | 23 + src/Layers/xrRenderPC_GL/gl_R_render.cpp | 444 +++++++ src/Layers/xrRenderPC_GL/gl_loader.cpp | 389 ++++++ src/Layers/xrRenderPC_GL/gl_rendertarget.cpp | 748 +++++++++++ src/Layers/xrRenderPC_GL/gl_rendertarget.h | 269 ++++ .../gl_rendertarget_accum_direct.cpp | 578 +++++++++ .../gl_rendertarget_accum_omnipart_geom.cpp | 30 + .../gl_rendertarget_accum_point.cpp | 117 ++ .../gl_rendertarget_accum_point_geom.cpp | 312 +++++ .../gl_rendertarget_accum_reflected.cpp | 78 ++ .../gl_rendertarget_accum_spot.cpp | 458 +++++++ .../gl_rendertarget_accum_spot_geom.cpp | 188 +++ .../gl_rendertarget_draw_volume.cpp | 25 + .../gl_rendertarget_enable_scissor.cpp | 167 +++ .../gl_rendertarget_phase_PP.cpp | 140 ++ .../gl_rendertarget_phase_accumulator.cpp | 61 + .../gl_rendertarget_phase_bloom.cpp | 328 +++++ .../gl_rendertarget_phase_combine.cpp | 533 ++++++++ .../gl_rendertarget_phase_luminance.cpp | 136 ++ .../gl_rendertarget_phase_occq.cpp | 10 + .../gl_rendertarget_phase_scene.cpp | 104 ++ .../gl_rendertarget_phase_smap_D.cpp | 64 + .../gl_rendertarget_phase_smap_S.cpp | 70 + .../gl_rendertarget_phase_ssao.cpp | 121 ++ .../xrRenderPC_GL/gl_rendertarget_wallmarks.h | 1 + src/Layers/xrRenderPC_GL/glr_constants.cpp | 166 +++ src/Layers/xrRenderPC_GL/r2_R_calculate.cpp | 71 ++ src/Layers/xrRenderPC_GL/r2_R_lights.cpp | 235 ++++ src/Layers/xrRenderPC_GL/r2_R_sun.cpp | 1125 +++++++++++++++++ src/Layers/xrRenderPC_GL/r2_blenders.cpp | 51 + src/Layers/xrRenderPC_GL/r2_sector_detect.cpp | 81 ++ src/Layers/xrRenderPC_GL/r2_types.h | 101 ++ src/Layers/xrRenderPC_GL/rgl.cpp | 632 +++++++++ src/Layers/xrRenderPC_GL/rgl.h | 347 +++++ src/Layers/xrRenderPC_GL/stdafx.cpp | 8 + src/Layers/xrRenderPC_GL/stdafx.h | 58 + src/Layers/xrRenderPC_GL/xrRender_GL.cpp | 36 + src/Layers/xrRenderPC_GL/xrRender_GL.vcxproj | 543 ++++++++ .../xrRenderPC_GL/xrRender_GL.vcxproj.filters | 1080 ++++++++++++++++ src/Layers/xrRenderPC_R1/stdafx.h | 1 + src/Layers/xrRenderPC_R2/stdafx.h | 1 + src/Layers/xrRenderPC_R3/stdafx.h | 1 + src/Layers/xrRenderPC_R4/stdafx.h | 1 + src/engine.sln | 544 +++++++- 121 files changed, 17698 insertions(+), 4 deletions(-) create mode 100644 src/Layers/xrRenderGL/glBufferUtils.cpp create mode 100644 src/Layers/xrRenderGL/glBufferUtils.h create mode 100644 src/Layers/xrRenderGL/glDetailManager_VS.cpp create mode 100644 src/Layers/xrRenderGL/glR_Backend_Runtime.h create mode 100644 src/Layers/xrRenderGL/glSH_RT.cpp create mode 100644 src/Layers/xrRenderGL/glSH_Texture.cpp create mode 100644 src/Layers/xrRenderGL/glState.cpp create mode 100644 src/Layers/xrRenderGL/glState.h create mode 100644 src/Layers/xrRenderGL/glStateUtils.cpp create mode 100644 src/Layers/xrRenderGL/glStateUtils.h create mode 100644 src/Layers/xrRenderGL/glTextureUtils.cpp create mode 100644 src/Layers/xrRenderGL/glTextureUtils.h create mode 100644 src/Layers/xrRenderGL/glr_constants_cache.h create mode 100644 src/Layers/xrRenderPC_GL/GLUtils.cpp create mode 100644 src/Layers/xrRenderPC_GL/GLUtils.h create mode 100644 src/Layers/xrRenderPC_GL/GL_DStreams.cpp create mode 100644 src/Layers/xrRenderPC_GL/SMAP_Allocator.h create mode 100644 src/Layers/xrRenderPC_GL/blender_bloom_build.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_bloom_build.h create mode 100644 src/Layers/xrRenderPC_GL/blender_combine.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_combine.h create mode 100644 src/Layers/xrRenderPC_GL/blender_deffer_aref.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_deffer_aref.h create mode 100644 src/Layers/xrRenderPC_GL/blender_deffer_flat.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_deffer_flat.h create mode 100644 src/Layers/xrRenderPC_GL/blender_deffer_model.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_deffer_model.h create mode 100644 src/Layers/xrRenderPC_GL/blender_light_direct.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_light_direct.h create mode 100644 src/Layers/xrRenderPC_GL/blender_light_mask.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_light_mask.h create mode 100644 src/Layers/xrRenderPC_GL/blender_light_occq.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_light_occq.h create mode 100644 src/Layers/xrRenderPC_GL/blender_light_point.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_light_point.h create mode 100644 src/Layers/xrRenderPC_GL/blender_light_reflected.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_light_reflected.h create mode 100644 src/Layers/xrRenderPC_GL/blender_light_spot.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_light_spot.h create mode 100644 src/Layers/xrRenderPC_GL/blender_luminance.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_luminance.h create mode 100644 src/Layers/xrRenderPC_GL/blender_ssao.cpp create mode 100644 src/Layers/xrRenderPC_GL/blender_ssao.h create mode 100644 src/Layers/xrRenderPC_GL/glApplicationRender.cpp create mode 100644 src/Layers/xrRenderPC_GL/glApplicationRender.h create mode 100644 src/Layers/xrRenderPC_GL/glDebugRender.cpp create mode 100644 src/Layers/xrRenderPC_GL/glDebugRender.h create mode 100644 src/Layers/xrRenderPC_GL/glEnvironmentRender.cpp create mode 100644 src/Layers/xrRenderPC_GL/glEnvironmentRender.h create mode 100644 src/Layers/xrRenderPC_GL/glFontRender.cpp create mode 100644 src/Layers/xrRenderPC_GL/glFontRender.h create mode 100644 src/Layers/xrRenderPC_GL/glLensFlareRender.cpp create mode 100644 src/Layers/xrRenderPC_GL/glLensFlareRender.h create mode 100644 src/Layers/xrRenderPC_GL/glObjectSpaceRender.cpp create mode 100644 src/Layers/xrRenderPC_GL/glObjectSpaceRender.h create mode 100644 src/Layers/xrRenderPC_GL/glRainRender.cpp create mode 100644 src/Layers/xrRenderPC_GL/glRainRender.h create mode 100644 src/Layers/xrRenderPC_GL/glRenderDeviceRender.cpp create mode 100644 src/Layers/xrRenderPC_GL/glRenderDeviceRender.h create mode 100644 src/Layers/xrRenderPC_GL/glRenderFactory.cpp create mode 100644 src/Layers/xrRenderPC_GL/glRenderFactory.h create mode 100644 src/Layers/xrRenderPC_GL/glResourceManager_Resources.cpp create mode 100644 src/Layers/xrRenderPC_GL/glResourceManager_Scripting.cpp create mode 100644 src/Layers/xrRenderPC_GL/glStatsRender.cpp create mode 100644 src/Layers/xrRenderPC_GL/glStatsRender.h create mode 100644 src/Layers/xrRenderPC_GL/glTexture.cpp create mode 100644 src/Layers/xrRenderPC_GL/glThunderboltDescRender.cpp create mode 100644 src/Layers/xrRenderPC_GL/glThunderboltDescRender.h create mode 100644 src/Layers/xrRenderPC_GL/glThunderboltRender.cpp create mode 100644 src/Layers/xrRenderPC_GL/glThunderboltRender.h create mode 100644 src/Layers/xrRenderPC_GL/glUIRender.cpp create mode 100644 src/Layers/xrRenderPC_GL/glUIRender.h create mode 100644 src/Layers/xrRenderPC_GL/glUISequenceVideoItem.cpp create mode 100644 src/Layers/xrRenderPC_GL/glUISequenceVideoItem.h create mode 100644 src/Layers/xrRenderPC_GL/glUIShader.cpp create mode 100644 src/Layers/xrRenderPC_GL/glUIShader.h create mode 100644 src/Layers/xrRenderPC_GL/glWallMarkArray.cpp create mode 100644 src/Layers/xrRenderPC_GL/glWallMarkArray.h create mode 100644 src/Layers/xrRenderPC_GL/gl_R_render.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_loader.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget.h create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_accum_direct.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_accum_omnipart_geom.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_accum_point.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_accum_point_geom.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_accum_reflected.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_accum_spot.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_accum_spot_geom.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_draw_volume.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_enable_scissor.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_phase_PP.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_phase_accumulator.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_phase_bloom.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_phase_combine.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_phase_luminance.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_phase_occq.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_phase_scene.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_phase_smap_D.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_phase_smap_S.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_phase_ssao.cpp create mode 100644 src/Layers/xrRenderPC_GL/gl_rendertarget_wallmarks.h create mode 100644 src/Layers/xrRenderPC_GL/glr_constants.cpp create mode 100644 src/Layers/xrRenderPC_GL/r2_R_calculate.cpp create mode 100644 src/Layers/xrRenderPC_GL/r2_R_lights.cpp create mode 100644 src/Layers/xrRenderPC_GL/r2_R_sun.cpp create mode 100644 src/Layers/xrRenderPC_GL/r2_blenders.cpp create mode 100644 src/Layers/xrRenderPC_GL/r2_sector_detect.cpp create mode 100644 src/Layers/xrRenderPC_GL/r2_types.h create mode 100644 src/Layers/xrRenderPC_GL/rgl.cpp create mode 100644 src/Layers/xrRenderPC_GL/rgl.h create mode 100644 src/Layers/xrRenderPC_GL/stdafx.cpp create mode 100644 src/Layers/xrRenderPC_GL/stdafx.h create mode 100644 src/Layers/xrRenderPC_GL/xrRender_GL.cpp create mode 100644 src/Layers/xrRenderPC_GL/xrRender_GL.vcxproj create mode 100644 src/Layers/xrRenderPC_GL/xrRender_GL.vcxproj.filters diff --git a/src/Layers/xrRenderGL/glBufferUtils.cpp b/src/Layers/xrRenderGL/glBufferUtils.cpp new file mode 100644 index 00000000000..cb06d537efc --- /dev/null +++ b/src/Layers/xrRenderGL/glBufferUtils.cpp @@ -0,0 +1,282 @@ +#include "stdafx.h" +#include "glBufferUtils.h" + +namespace glBufferUtils +{ + + void CreateBuffer(GLuint* pBuffer, const void* pData, UINT DataSize, bool bImmutable, bool bIndexBuffer) +{ + GLenum usage = bImmutable ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW; + GLenum target = bIndexBuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER; + + glGenBuffers(1, pBuffer); + glBindBuffer(target, *pBuffer); + CHK_GL(glBufferData(target, DataSize, pData, usage)); +} + +void CreateVertexBuffer(GLuint* pBuffer, const void* pData, UINT DataSize, bool bImmutable) +{ + return CreateBuffer(pBuffer, pData, DataSize, bImmutable, false); +} + +void CreateIndexBuffer(GLuint* pBuffer, const void* pData, UINT DataSize, bool bImmutable) +{ + return CreateBuffer(pBuffer, pData, DataSize, bImmutable, true); +} + +GLenum VertexSizeList[] = +{ + 1, // D3DDECLTYPE_FLOAT1 + 2, // D3DDECLTYPE_FLOAT2 + 3, // D3DDECLTYPE_FLOAT3 + 4, // D3DDECLTYPE_FLOAT4 + 4, // D3DDECLTYPE_D3DCOLOR + 4, // D3DDECLTYPE_UBYTE4 + 2, // D3DDECLTYPE_SHORT2 + 4, // D3DDECLTYPE_SHORT4 + 4, // D3DDECLTYPE_UBYTE4N + 2, // D3DDECLTYPE_SHORT2N + 4, // D3DDECLTYPE_SHORT4N + 2, // D3DDECLTYPE_USHORT2N + 4, // D3DDECLTYPE_USHORT4N + 1, // D3DDECLTYPE_UDEC3 + 1, // D3DDECLTYPE_DEC3N + 2, // D3DDECLTYPE_FLOAT16_2 + 4 // D3DDECLTYPE_FLOAT16_4 +}; + +GLenum VertexTypeList[] = +{ + GL_FLOAT, // D3DDECLTYPE_FLOAT1 + GL_FLOAT, // D3DDECLTYPE_FLOAT2 + GL_FLOAT, // D3DDECLTYPE_FLOAT3 + GL_FLOAT, // D3DDECLTYPE_FLOAT4 + GL_UNSIGNED_BYTE, // D3DDECLTYPE_D3DCOLOR + GL_UNSIGNED_BYTE, // D3DDECLTYPE_UBYTE4 + GL_SHORT, // D3DDECLTYPE_SHORT2 + GL_SHORT, // D3DDECLTYPE_SHORT4 + GL_UNSIGNED_BYTE, // D3DDECLTYPE_UBYTE4N + GL_SHORT, // D3DDECLTYPE_SHORT2N + GL_SHORT, // D3DDECLTYPE_SHORT4N + GL_UNSIGNED_SHORT, // D3DDECLTYPE_USHORT2N + GL_UNSIGNED_SHORT, // D3DDECLTYPE_USHORT4N + GL_INT_2_10_10_10_REV, // D3DDECLTYPE_UDEC3 + GL_INT_2_10_10_10_REV, // D3DDECLTYPE_DEC3N + GL_HALF_FLOAT, // D3DDECLTYPE_FLOAT16_2 + GL_HALF_FLOAT // D3DDECLTYPE_FLOAT16_4 +}; + +GLenum VertexNormalizedList[] = +{ + GL_FALSE, // D3DDECLTYPE_FLOAT1 + GL_FALSE, // D3DDECLTYPE_FLOAT2 + GL_FALSE, // D3DDECLTYPE_FLOAT3 + GL_FALSE, // D3DDECLTYPE_FLOAT4 + GL_TRUE, // D3DDECLTYPE_D3DCOLOR + GL_FALSE, // D3DDECLTYPE_UBYTE4 + GL_FALSE, // D3DDECLTYPE_SHORT2 + GL_FALSE, // D3DDECLTYPE_SHORT4 + GL_TRUE, // D3DDECLTYPE_UBYTE4N + GL_TRUE, // D3DDECLTYPE_SHORT2N + GL_TRUE, // D3DDECLTYPE_SHORT4N + GL_TRUE, // D3DDECLTYPE_USHORT2N + GL_TRUE, // D3DDECLTYPE_USHORT4N + GL_FALSE, // D3DDECLTYPE_UDEC3 + GL_TRUE, // D3DDECLTYPE_DEC3N + GL_FALSE, // D3DDECLTYPE_FLOAT16_2 + GL_FALSE // D3DDECLTYPE_FLOAT16_4 +}; + +GLenum VertexTypeSizeList[] = +{ + sizeof(GLfloat), // D3DDECLTYPE_FLOAT1 + sizeof(GLfloat), // D3DDECLTYPE_FLOAT2 + sizeof(GLfloat), // D3DDECLTYPE_FLOAT3 + sizeof(GLfloat), // D3DDECLTYPE_FLOAT4 + sizeof(GLubyte), // D3DDECLTYPE_D3DCOLOR + sizeof(GLubyte), // D3DDECLTYPE_UBYTE4 + sizeof(GLshort), // D3DDECLTYPE_SHORT2 + sizeof(GLshort), // D3DDECLTYPE_SHORT4 + sizeof(GLubyte), // D3DDECLTYPE_UBYTE4N + sizeof(GLshort), // D3DDECLTYPE_SHORT2N + sizeof(GLshort), // D3DDECLTYPE_SHORT4N + sizeof(GLushort), // D3DDECLTYPE_USHORT2N + sizeof(GLushort), // D3DDECLTYPE_USHORT4N + sizeof(GLuint), // D3DDECLTYPE_UDEC3 + sizeof(GLint), // D3DDECLTYPE_DEC3N + sizeof(GLhalf), // D3DDECLTYPE_FLOAT16_2 + sizeof(GLhalf) // D3DDECLTYPE_FLOAT16_4 +}; + +GLuint VertexUsageList[] = +{ + 3, // D3DDECLUSAGE_POSITION + -1, // D3DDECLUSAGE_BLENDWEIGHT + -1, // D3DDECLUSAGE_BLENDINDICES + 5, // D3DDECLUSAGE_NORMAL + -1, // D3DDECLUSAGE_PSIZE + 8, // D3DDECLUSAGE_TEXCOORD + 4, // D3DDECLUSAGE_TANGENT + 6, // D3DDECLUSAGE_BINORMAL + -1, // D3DDECLUSAGE_TESSFACTOR + -1, // D3DDECLUSAGE_POSITIONT + 0, // D3DDECLUSAGE_COLOR + 7, // D3DDECLUSAGE_FOG + -1, // D3DDECLUSAGE_DEPTH + -1, // D3DDECLUSAGE_SAMPLE +}; + +GLsizei GetDeclVertexSize(const D3DVERTEXELEMENT9* decl) +{ + GLsizei size = 0; + for (int i = 0; i < MAXD3DDECLLENGTH; ++i) + { + const D3DVERTEXELEMENT9 &desc = decl[i]; + + if (desc.Stream == 0xFF) + break; + + size += VertexSizeList[desc.Type] * VertexTypeSizeList[desc.Type]; + } + return size; +} + +void ConvertVertexDeclaration(const D3DVERTEXELEMENT9* decl, GLuint vao) +{ + CHK_GL(glBindVertexArray(vao)); + + GLsizei stride = GetDeclVertexSize(decl); + for (int i = 0; i < MAXD3DDECLLENGTH; ++i) + { + const D3DVERTEXELEMENT9 &desc = decl[i]; + + if (desc.Stream == 0xFF) + break; + + GLuint location = VertexUsageList[desc.Usage]; + GLint size = VertexSizeList[desc.Type]; + GLenum type = VertexTypeList[desc.Type]; + GLboolean normalized = VertexNormalizedList[desc.Type]; + + if (location < 0) + continue; // Unsupported + + location += desc.UsageIndex; + CHK_GL(glVertexAttribFormat(location, size, type, normalized, desc.Offset)); + CHK_GL(glVertexAttribBinding(location, desc.Stream)); + CHK_GL(glEnableVertexAttribArray(location)); + } +} + +GLsizei GetFVFVertexSize(u32 FVF) +{ + GLsizei offset = 0; + + // Position attribute + if (FVF & D3DFVF_XYZRHW) + offset += sizeof(Fvector4); + else if (FVF & D3DFVF_XYZ) + offset += sizeof(Fvector); + + // Diffuse color attribute + if (FVF & D3DFVF_DIFFUSE) + offset += sizeof(u32); + + // Specular color attribute + if (FVF & D3DFVF_SPECULAR) + offset += sizeof(u32); + + // Texture coordinates + for (u32 i = 0; i < (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; i++) + { + u32 size = 2; + if (FVF & D3DFVF_TEXCOORDSIZE1(i)) + size = 1; + if (FVF & D3DFVF_TEXCOORDSIZE3(i)) + size = 3; + if (FVF & D3DFVF_TEXCOORDSIZE4(i)) + size = 4; + + offset += size * sizeof(float); + } + + return offset; +} + +void ConvertVertexDeclaration(u32 FVF, GLuint vao) +{ + CHK_GL(glBindVertexArray(vao)); + + GLsizei stride = GetFVFVertexSize(FVF); + u32 offset = 0; + + // Position attribute + if (FVF & D3DFVF_XYZRHW) + { + GLuint attrib = VertexUsageList[D3DDECLUSAGE_POSITION]; + CHK_GL(glVertexAttribFormat(attrib, 4, GL_FLOAT, GL_FALSE, offset)); + CHK_GL(glVertexAttribBinding(attrib, 0)); + CHK_GL(glEnableVertexAttribArray(attrib)); + offset += sizeof(Fvector4); + } + else if (FVF & D3DFVF_XYZ) + { + GLuint attrib = VertexUsageList[D3DDECLUSAGE_POSITION]; + CHK_GL(glVertexAttribFormat(attrib, 3, GL_FLOAT, GL_FALSE, offset)); + CHK_GL(glVertexAttribBinding(attrib, 0)); + CHK_GL(glEnableVertexAttribArray(attrib)); + offset += sizeof(Fvector); + } + + // Diffuse color attribute + if (FVF & D3DFVF_DIFFUSE) + { + GLuint attrib = VertexUsageList[D3DDECLUSAGE_COLOR]; + CHK_GL(glVertexAttribFormat(attrib, 4, GL_UNSIGNED_BYTE, GL_TRUE, offset)); + CHK_GL(glVertexAttribBinding(attrib, 0)); + CHK_GL(glEnableVertexAttribArray(attrib)); + offset += sizeof(u32); + } + + // Specular color attribute + if (FVF & D3DFVF_SPECULAR) + { + GLuint attrib = VertexUsageList[D3DDECLUSAGE_COLOR] + 1; + CHK_GL(glVertexAttribFormat(attrib, 4, GL_UNSIGNED_BYTE, GL_TRUE, offset)); + CHK_GL(glVertexAttribBinding(attrib, 0)); + CHK_GL(glEnableVertexAttribArray(attrib)); + offset += sizeof(u32); + } + + // Texture coordinates + for (u32 i = 0; i < (FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; i++) + { + GLuint attrib = VertexUsageList[D3DDECLUSAGE_TEXCOORD] + i; + + u32 size = 2; + if (FVF & D3DFVF_TEXCOORDSIZE1(i)) + size = 1; + if (FVF & D3DFVF_TEXCOORDSIZE3(i)) + size = 3; + if (FVF & D3DFVF_TEXCOORDSIZE4(i)) + size = 4; + + CHK_GL(glVertexAttribFormat(attrib, size, GL_FLOAT, GL_TRUE, offset)); + CHK_GL(glVertexAttribBinding(attrib, 0)); + CHK_GL(glEnableVertexAttribArray(attrib)); + offset += size * sizeof(float); + } + + VERIFY(stride == offset); +} + +u32 GetDeclLength(const D3DVERTEXELEMENT9 *decl) +{ + const D3DVERTEXELEMENT9 *element; + + for (element = decl; element->Stream != 0xff; ++element); + + return element - decl; +} + +}; diff --git a/src/Layers/xrRenderGL/glBufferUtils.h b/src/Layers/xrRenderGL/glBufferUtils.h new file mode 100644 index 00000000000..96cf523573d --- /dev/null +++ b/src/Layers/xrRenderGL/glBufferUtils.h @@ -0,0 +1,16 @@ +#pragma once + +#ifdef USE_OGL + +namespace glBufferUtils +{ + void CreateVertexBuffer(GLuint* pBuffer, const void* pData, UINT DataSize, bool bImmutable = true); + void CreateIndexBuffer(GLuint* pBuffer, const void* pData, UINT DataSize, bool bImmutable = true); + GLsizei GetFVFVertexSize(u32 FVF); + GLsizei GetDeclVertexSize(const D3DVERTEXELEMENT9* decl); + u32 GetDeclLength(const D3DVERTEXELEMENT9* decl); + void ConvertVertexDeclaration(u32 FVF, GLuint vao); + void ConvertVertexDeclaration(const D3DVERTEXELEMENT9* decl, GLuint vao); +}; + +#endif // USE_OGL diff --git a/src/Layers/xrRenderGL/glDetailManager_VS.cpp b/src/Layers/xrRenderGL/glDetailManager_VS.cpp new file mode 100644 index 00000000000..1becc8daaf6 --- /dev/null +++ b/src/Layers/xrRenderGL/glDetailManager_VS.cpp @@ -0,0 +1,225 @@ +#include "stdafx.h" +#include "../xrRender/DetailManager.h" + +#include "../../xrEngine/igame_persistent.h" +#include "../../xrEngine/environment.h" + +#include "../xrRenderGL/glBufferUtils.h" + +const int quant = 16384; +const int c_hdr = 10; +const int c_size = 4; + +#pragma pack(push,1) +struct vertHW +{ + float x,y,z; + short u,v,t,mid; +}; +#pragma pack(pop) + +short QC (float v); +//{ +// int t=iFloor(v*float(quant)); clamp(t,-32768,32767); +// return short(t&0xffff); +//} + +void CDetailManager::hw_Load_Shaders() +{ + // Create shader to access constant storage + ref_shader S; S.create("details\\set"); + R_constant_table& T0 = *(S->E[0]->passes[0]->constants); + R_constant_table& T1 = *(S->E[1]->passes[0]->constants); + hwc_consts = T0.get("consts"); + hwc_wave = T0.get("wave"); + hwc_wind = T0.get("dir2D"); + hwc_array = T0.get("array"); + hwc_s_consts = T1.get("consts"); + hwc_s_xform = T1.get("xform"); + hwc_s_array = T1.get("array"); +} + +void CDetailManager::hw_Render() +{ + // Render-prepare + // Update timer + // Can't use Device.fTimeDelta since it is smoothed! Don't know why, but smoothed value looks more choppy! + float fDelta = Device.fTimeGlobal-m_global_time_old; + if ( (fDelta<0) || (fDelta>1)) fDelta = 0.03; + m_global_time_old = Device.fTimeGlobal; + + m_time_rot_1 += (PI_MUL_2*fDelta/swing_current.rot1); + m_time_rot_2 += (PI_MUL_2*fDelta/swing_current.rot2); + m_time_pos += fDelta*swing_current.speed; + + //float tm_rot1 = (PI_MUL_2*Device.fTimeGlobal/swing_current.rot1); + //float tm_rot2 = (PI_MUL_2*Device.fTimeGlobal/swing_current.rot2); + float tm_rot1 = m_time_rot_1; + float tm_rot2 = m_time_rot_2; + + Fvector4 dir1,dir2; + dir1.set (_sin(tm_rot1),0,_cos(tm_rot1),0).normalize().mul(swing_current.amp1); + dir2.set (_sin(tm_rot2),0,_cos(tm_rot2),0).normalize().mul(swing_current.amp2); + + // Setup geometry and DMA + RCache.set_Geometry (hw_Geom); + + // Wave0 + float scale = 1.f/float(quant); + Fvector4 wave; + Fvector4 consts; + consts.set (scale, scale, ps_r__Detail_l_aniso, ps_r__Detail_l_ambient); + //wave.set (1.f/5.f, 1.f/7.f, 1.f/3.f, Device.fTimeGlobal*swing_current.speed); + wave.set (1.f/5.f, 1.f/7.f, 1.f/3.f, m_time_pos); + //RCache.set_c (&*hwc_consts, scale, scale, ps_r__Detail_l_aniso, ps_r__Detail_l_ambient); // consts + //RCache.set_c (&*hwc_wave, wave.div(PI_MUL_2)); // wave + //RCache.set_c (&*hwc_wind, dir1); // wind-dir + //hw_Render_dump (&*hwc_array, 1, 0, c_hdr ); + hw_Render_dump(consts, wave.div(PI_MUL_2), dir1, 1, 0); + + // Wave1 + //wave.set (1.f/3.f, 1.f/7.f, 1.f/5.f, Device.fTimeGlobal*swing_current.speed); + wave.set (1.f/3.f, 1.f/7.f, 1.f/5.f, m_time_pos); + //RCache.set_c (&*hwc_wave, wave.div(PI_MUL_2)); // wave + //RCache.set_c (&*hwc_wind, dir2); // wind-dir + //hw_Render_dump (&*hwc_array, 2, 0, c_hdr ); + hw_Render_dump(consts, wave.div(PI_MUL_2), dir2, 2, 0); + + // Still + consts.set (scale, scale, scale, 1.f); + //RCache.set_c (&*hwc_s_consts,scale, scale, scale, 1.f); + //RCache.set_c (&*hwc_s_xform, Device.mFullTransform); + //hw_Render_dump (&*hwc_s_array, 0, 1, c_hdr ); + hw_Render_dump(consts, wave.div(PI_MUL_2), dir2, 0, 1); +} + +void CDetailManager::hw_Render_dump(const Fvector4 &consts, const Fvector4 &wave, const Fvector4 &wind, u32 var_id, u32 lod_id) +{ + static shared_str strConsts("consts"); + static shared_str strWave("wave"); + static shared_str strDir2D("dir2D"); + static shared_str strArray("array"); + static shared_str strXForm("xform"); + + Device.Statistic->RenderDUMP_DT_Count = 0; + + // Matrices and offsets + u32 vOffset = 0; + u32 iOffset = 0; + + vis_list& list = m_visibles [var_id]; + + CEnvDescriptor& desc = *g_pGamePersistent->Environment().CurrentEnv; + Fvector c_sun,c_ambient,c_hemi; + c_sun.set (desc.sun_color.x, desc.sun_color.y, desc.sun_color.z); c_sun.mul(.5f); + c_ambient.set (desc.ambient.x, desc.ambient.y, desc.ambient.z); + c_hemi.set (desc.hemi_color.x, desc.hemi_color.y, desc.hemi_color.z); + + // Iterate + for (u32 O=0; O& vis = list [O]; + if (!vis.empty()) + { + for ( u32 iPass=0; iPassE[lod_id]->passes.size(); ++iPass) + { + // Setup matrices + colors (and flush it as necessary) + //RCache.set_Element (Object.shader->E[lod_id]); + RCache.set_Element (Object.shader->E[lod_id], iPass); + RImplementation.apply_lmaterial (); + + // This could be cached in the corresponding consatant buffer + // as it is done for DX9 + RCache.set_c(strConsts, consts); + RCache.set_c(strWave, wave); + RCache.set_c(strDir2D, wind); + RCache.set_c(strXForm, Device.mFullTransform); + + ref_constant constArray = RCache.get_c(strArray); + VERIFY(constArray); + + //u32 c_base = x_array->vs.index; + //Fvector4* c_storage = RCache.get_ConstantCache_Vertex().get_array_f().access(c_base); + // TODO: OGL: Implement a constants buffer. + /*Fvector4* c_storage=0; + // Map constants to memory directly + { + void* pVData; + RCache.get_ConstantDirect( strArray, + hw_BatchSize*sizeof(Fvector4)*4, + &pVData, 0, 0); + c_storage = (Fvector4*) pVData; + } + VERIFY(c_storage);*/ + + u32 dwBatch = 0; + + xr_vector ::iterator _vI = vis.begin(); + xr_vector ::iterator _vE = vis.end(); + for (; _vI!=_vE; _vI++){ + SlotItemVec* items = *_vI; + SlotItemVecIt _iI = items->begin(); + SlotItemVecIt _iE = items->end(); + for (; _iI!=_iE; _iI++){ + SlotItem& Instance = **_iI; + u32 base = dwBatch*4; + + // Build matrix ( 3x4 matrix, last row - color ) + float scale = Instance.scale_calculated; + Fmatrix& M = Instance.mRotY; + RCache.set_ca(&*constArray, base+0, M._11*scale, M._21*scale, M._31*scale, M._41 ); + RCache.set_ca(&*constArray, base+1, M._12*scale, M._22*scale, M._32*scale, M._42 ); + RCache.set_ca(&*constArray, base+2, M._13*scale, M._23*scale, M._33*scale, M._43 ); + + // Build color + // R2 only needs hemisphere + float h = Instance.c_hemi; + float s = Instance.c_sun; + RCache.set_ca(&*constArray, base+3, s, s, s, h ); + dwBatch ++; + if (dwBatch == hw_BatchSize) { + // flush + Device.Statistic->RenderDUMP_DT_Count += dwBatch; + u32 dwCNT_verts = dwBatch * Object.number_vertices; + u32 dwCNT_prims = (dwBatch * Object.number_indices)/3; + //RCache.get_ConstantCache_Vertex().b_dirty = TRUE; + //RCache.get_ConstantCache_Vertex().get_array_f().dirty (c_base,c_base+dwBatch*4); + RCache.Render (D3DPT_TRIANGLELIST,vOffset, 0, dwCNT_verts,iOffset,dwCNT_prims); + RCache.stat.r.s_details.add (dwCNT_verts); + + // restart + dwBatch = 0; + + // Remap constants to memory directly (just in case anything goes wrong) + /*{ + void* pVData; + RCache.get_ConstantDirect( strArray, + hw_BatchSize*sizeof(Fvector4)*4, + &pVData, 0, 0); + c_storage = (Fvector4*) pVData; + } + VERIFY(c_storage);*/ + } + } + } + // flush if nessecary + if (dwBatch) + { + Device.Statistic->RenderDUMP_DT_Count += dwBatch; + u32 dwCNT_verts = dwBatch * Object.number_vertices; + u32 dwCNT_prims = (dwBatch * Object.number_indices)/3; + //RCache.get_ConstantCache_Vertex().b_dirty = TRUE; + //RCache.get_ConstantCache_Vertex().get_array_f().dirty (c_base,c_base+dwBatch*4); + RCache.Render (D3DPT_TRIANGLELIST,vOffset,0,dwCNT_verts,iOffset,dwCNT_prims); + RCache.stat.r.s_details.add (dwCNT_verts); + } + + } + // Clean up + vis.clear_not_free (); + } + vOffset += hw_BatchSize * Object.number_vertices; + iOffset += hw_BatchSize * Object.number_indices; + } +} diff --git a/src/Layers/xrRenderGL/glR_Backend_Runtime.h b/src/Layers/xrRenderGL/glR_Backend_Runtime.h new file mode 100644 index 00000000000..21bad803d9b --- /dev/null +++ b/src/Layers/xrRenderGL/glR_Backend_Runtime.h @@ -0,0 +1,318 @@ +#ifndef glR_Backend_Runtime_included +#define glR_Backend_Runtime_included +#pragma once + +#include "../xrRenderGL/glStateUtils.h" + +IC void CBackend::set_xform(u32 ID, const Fmatrix& M) +{ + stat.xforms++; + // TODO: OGL: Implement CBackend::set_xform + //VERIFY(!"Implement CBackend::set_xform"); +} + +IC void CBackend::set_FB(GLuint FB) +{ + if (FB != pFB) + { + PGO(Msg("PGO:set_FB")); + pFB = FB; + CHK_GL(glBindFramebuffer(GL_FRAMEBUFFER, pFB)); + + // Clear cached attachments + pRT[0] = pRT[1] = pRT[2] = pRT[3] = pZB = NULL; + } +} + +IC void CBackend::set_RT(GLuint RT, u32 ID) +{ + if (RT != pRT[ID]) + { + PGO(Msg("PGO:setRT")); + stat.target_rt++; + pRT[ID] = RT; + CHK_GL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + ID, GL_TEXTURE_2D, RT, 0)); + } +} + +IC void CBackend::set_ZB(GLuint ZB) +{ + if (ZB != pZB) + { + PGO(Msg("PGO:setZB")); + stat.target_zb++; + pZB = ZB; + CHK_GL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, ZB, 0)); + } +} + +ICF void CBackend::set_Format(SDeclaration* _decl) +{ + if (decl != _decl) + { + PGO(Msg("PGO:v_format:%x", _decl)); +#ifdef DEBUG + stat.decl++; +#endif + decl = _decl; + CHK_GL(glBindVertexArray(_decl->vao)); + + // Clear cached index buffer + ib = 0; + } +} + +ICF void CBackend::set_PS(GLuint _ps, LPCSTR _n) +{ + if (ps != _ps) + { + string_path name; + PGO(glGetObjectLabel(GL_PROGRAM, _ps, sizeof(name), nullptr, name)); + PGO(Msg("PGO:Pshader:%d,%s", _ps, _n ? _n : name)); + stat.ps++; + ps = _ps; + CHK_GL(glUseProgramStages(pp, GL_FRAGMENT_SHADER_BIT, ps)); +#ifdef DEBUG + ps_name = _n; +#endif + } +} + +ICF void CBackend::set_VS(GLuint _vs, LPCSTR _n) +{ + if (vs != _vs) + { + string_path name; + PGO(glGetObjectLabel(GL_PROGRAM, _vs, sizeof(name), nullptr, name)); + PGO(Msg("PGO:Vshader:%d,%s", _vs, _n ? _n : name)); + stat.vs++; + vs = _vs; + CHK_GL(glUseProgramStages(pp, GL_VERTEX_SHADER_BIT, vs)); +#ifdef DEBUG + vs_name = _n; +#endif + } +} + +ICF void CBackend::set_Vertices(GLuint _vb, u32 _vb_stride) +{ + if ((vb != _vb) || (vb_stride != _vb_stride)) + { + PGO(Msg("PGO:VB:%x,%d", _vb, _vb_stride)); +#ifdef DEBUG + stat.vb++; +#endif + vb = _vb; + vb_stride = _vb_stride; + CHK_GL(glBindVertexBuffer(0, vb, 0, vb_stride)); + } +} + +ICF void CBackend::set_Indices(GLuint _ib) +{ + if (ib != _ib) + { + PGO(Msg("PGO:IB:%x", _ib)); +#ifdef DEBUG + stat.ib++; +#endif + ib = _ib; + CHK_GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib)); + } +} + +IC GLenum TranslateTopology(D3DPRIMITIVETYPE T) +{ + static GLenum translateTable[] = + { + NULL, // None + GL_POINTS, // D3DPT_POINTLIST = 1, + GL_LINES, // D3DPT_LINELIST = 2, + GL_LINE_STRIP, // D3DPT_LINESTRIP = 3, + GL_TRIANGLES, // D3DPT_TRIANGLELIST = 4, + GL_TRIANGLE_STRIP, // D3DPT_TRIANGLESTRIP = 5, + GL_TRIANGLE_FAN, // D3DPT_TRIANGLEFAN = 6, + }; + + VERIFY(T= 0); + + GLenum result = translateTable[T]; + + VERIFY(result != NULL); + + return result; +} + +IC u32 GetIndexCount(D3DPRIMITIVETYPE T, u32 iPrimitiveCount) +{ + switch (T) + { + case D3DPT_POINTLIST: + return iPrimitiveCount; + case D3DPT_LINELIST: + return iPrimitiveCount * 2; + case D3DPT_LINESTRIP: + return iPrimitiveCount + 1; + case D3DPT_TRIANGLELIST: + return iPrimitiveCount * 3; + case D3DPT_TRIANGLESTRIP: + return iPrimitiveCount + 2; + default: NODEFAULT; +#ifdef DEBUG + return 0; +#endif // #ifdef DEBUG + } +} + +ICF void CBackend::Render(D3DPRIMITIVETYPE T, u32 baseV, u32 startV, u32 countV, u32 startI, u32 PC) +{ + GLenum Topology = TranslateTopology(T); + u32 iIndexCount = GetIndexCount(T, PC); + + stat.calls++; + stat.verts += countV; + stat.polys += PC; + constants.flush(); + CHK_GL(glBindProgramPipeline(pp)); + CHK_GL(glDrawElementsBaseVertex(Topology, iIndexCount, GL_UNSIGNED_SHORT, (void*)(startI * sizeof(GLushort)), baseV)); + PGO(Msg("PGO:DIP:%dv/%df", countV, PC)); +} + +ICF void CBackend::Render(D3DPRIMITIVETYPE T, u32 startV, u32 PC) +{ + GLenum Topology = TranslateTopology(T); + u32 iIndexCount = GetIndexCount(T, PC); + + stat.calls++; + stat.verts += iIndexCount; + stat.polys += PC; + constants.flush(); + CHK_GL(glBindProgramPipeline(pp)); + CHK_GL(glDrawArrays(Topology, startV, iIndexCount)); + PGO(Msg("PGO:DIP:%dv/%df", iIndexCount, PC)); +} + +IC void CBackend::set_Geometry(SGeometry* _geom) +{ + set_Format(&*_geom->dcl); + + set_Vertices(_geom->vb, _geom->vb_stride); + set_Indices(_geom->ib); +} + +IC void CBackend::set_Scissor(Irect* R) +{ + if (R) + { + CHK_GL(glEnable(GL_SCISSOR_TEST)); + + // The window space is inverted compared to DX, + // so we have to invert our vertical coordinates + u32 bottom = Device.dwHeight - R->bottom; + + // The origin of the scissor box is lower-left + CHK_GL(glScissor(R->left, bottom, R->width(), R->height())); + } + else + { + CHK_GL(glDisable(GL_SCISSOR_TEST)); + } +} + +IC void CBackend::set_Stencil(u32 _enable, u32 _func, u32 _ref, u32 _mask, u32 _writemask, u32 _fail, u32 _pass, u32 _zfail) +{ + if (_enable) + { + glEnable(GL_STENCIL_TEST); + CHK_GL(glStencilFunc(glStateUtils::ConvertCmpFunction(_func), _ref, _mask)); + CHK_GL(glStencilMask(_writemask)); + CHK_GL(glStencilOp(glStateUtils::ConvertStencilOp(_fail), + glStateUtils::ConvertStencilOp(_zfail), + glStateUtils::ConvertStencilOp(_pass))); + } + else + { + glDisable(GL_STENCIL_TEST); + } +} + +IC void CBackend::set_Z(u32 _enable) +{ + if (z_enable != _enable) + { + z_enable = _enable; + if (_enable) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); + } +} + +IC void CBackend::set_ZFunc(u32 _func) +{ + if (z_func != _func) + { + z_func = _func; + CHK_GL(glDepthFunc(glStateUtils::ConvertCmpFunction(_func))); + } +} + +IC void CBackend::set_AlphaRef(u32 _value) +{ + VERIFY(!"Not implemented."); +} + +IC void CBackend::set_ColorWriteEnable(u32 _mask) +{ + if (colorwrite_mask != _mask) { + colorwrite_mask = _mask; + CHK_GL(glColorMask( + _mask & D3DCOLORWRITEENABLE_RED, + _mask & D3DCOLORWRITEENABLE_GREEN, + _mask & D3DCOLORWRITEENABLE_BLUE, + _mask & D3DCOLORWRITEENABLE_ALPHA)); + } +} + +ICF void CBackend::set_CullMode(u32 _mode) +{ + if (cull_mode != _mode) { + cull_mode = _mode; + if (_mode == D3DCULL_NONE) { + glDisable(GL_CULL_FACE); + } + else { + glEnable(GL_CULL_FACE); + CHK_GL(glCullFace(glStateUtils::ConvertCullMode(_mode))); + } + } +} + +ICF void CBackend::set_VS(ref_vs& _vs) +{ + set_VS(_vs->vs, _vs->cName.c_str()); +} + +IC void CBackend::set_Constants(R_constant_table* C) +{ + // caching + if (ctable == C) return; + ctable = C; + xforms.unmap(); + hemi.unmap(); + tree.unmap(); + if (0 == C) return; + + PGO(Msg("PGO:c-table")); + + // process constant-loaders + R_constant_table::c_table::iterator it = C->table.begin(); + R_constant_table::c_table::iterator end = C->table.end(); + for (; it != end; it++) { + R_constant* Cs = &**it; + if (Cs->handler) Cs->handler->setup(Cs); + } +} + +#endif // glR_Backend_Runtime_included \ No newline at end of file diff --git a/src/Layers/xrRenderGL/glSH_RT.cpp b/src/Layers/xrRenderGL/glSH_RT.cpp new file mode 100644 index 00000000000..9edac22859d --- /dev/null +++ b/src/Layers/xrRenderGL/glSH_RT.cpp @@ -0,0 +1,76 @@ +#include "stdafx.h" +#pragma hdrstop + +#include "../xrRender/ResourceManager.h" + +#include "glRenderDeviceRender.h" + +#include "glTextureUtils.h" + +CRT::CRT () +{ + pSurface = NULL; + dwWidth = 0; + dwHeight = 0; + fmt = D3DFMT_UNKNOWN; +} +CRT::~CRT () +{ + destroy (); + + // release external reference + DEV->_DeleteRT (this); +} + +void CRT::create (LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount ) +{ + if (pSurface) return; + + R_ASSERT(Name && Name[0] && w && h); + _order = CPU::GetCLK(); //Device.GetTimerGlobal()->GetElapsed_clk(); + + //HRESULT _hr; + + dwWidth = w; + dwHeight = h; + fmt = f; + + // Get caps + GLint max_width, max_height; + CHK_GL(glGetIntegerv(GL_MAX_FRAMEBUFFER_WIDTH, &max_width)); + CHK_GL(glGetIntegerv(GL_MAX_FRAMEBUFFER_HEIGHT, &max_height)); + + // Check width-and-height of render target surface + if (w>max_width) return; + if (h>max_height) return; + + DEV->Evict(); + + glGenTextures(1, &pSurface); + CHK_GL(glBindTexture(GL_TEXTURE_2D, pSurface)); + CHK_GL(glTexStorage2D(GL_TEXTURE_2D, 1, glTextureUtils::ConvertTextureFormat(fmt), w, h)); + + pTexture = DEV->_CreateTexture (Name); + pTexture->surface_set(GL_TEXTURE_2D, pSurface); +} + +void CRT::destroy () +{ + if (pTexture._get()) { + pTexture->surface_set(GL_TEXTURE_2D, 0); + pTexture = NULL; + } + CHK_GL(glDeleteTextures(1, &pSurface)); +} +void CRT::reset_begin () +{ + destroy (); +} +void CRT::reset_end () +{ + create (*cName,dwWidth,dwHeight,fmt); +} +void resptrcode_crt::create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount) +{ + _set (DEV->_CreateRT(Name,w,h,f)); +} diff --git a/src/Layers/xrRenderGL/glSH_Texture.cpp b/src/Layers/xrRenderGL/glSH_Texture.cpp new file mode 100644 index 00000000000..e1e67a1c82a --- /dev/null +++ b/src/Layers/xrRenderGL/glSH_Texture.cpp @@ -0,0 +1,336 @@ +#include "stdafx.h" +#pragma hdrstop + +#include "../xrRender/ResourceManager.h" + +#ifndef _EDITOR +#include "../../xrEngine/render.h" +#endif + +#include "../../xrEngine/tntQAVI.h" +#include "../../xrEngine/xrTheora_Surface.h" + +#include "glRenderDeviceRender.h" + +#define PRIORITY_HIGH 12 +#define PRIORITY_NORMAL 8 +#define PRIORITY_LOW 4 + +void resptrcode_texture::create(LPCSTR _name) +{ + _set(DEV->_CreateTexture(_name)); +} + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +CTexture::CTexture () +{ + pSurface = NULL; + pBuffer = NULL; + pAVI = NULL; + pTheora = NULL; + desc = GL_TEXTURE_2D; + desc_cache = 0; + seqMSPF = 0; + flags.MemoryUsage = 0; + flags.bLoaded = false; + flags.bUser = false; + flags.seqCycles = FALSE; + m_material = 1.0f; + bind = fastdelegate::FastDelegate1(this,&CTexture::apply_load); +} + +CTexture::~CTexture() +{ + Unload (); + + // release external reference + DEV->_DeleteTexture (this); +} + +void CTexture::surface_set (GLenum target, GLuint surf ) +{ + desc = target; + pSurface = surf; +} + +GLuint CTexture::surface_get () +{ + return pSurface; +} + +void CTexture::PostLoad () +{ + if (pTheora) bind = fastdelegate::FastDelegate1(this,&CTexture::apply_theora); + else if (pAVI) bind = fastdelegate::FastDelegate1(this,&CTexture::apply_avi); + else if (!seqDATA.empty()) bind = fastdelegate::FastDelegate1(this,&CTexture::apply_seq); + else bind = fastdelegate::FastDelegate1(this,&CTexture::apply_normal); +} + +void CTexture::apply_load (u32 dwStage) { + CHK_GL(glActiveTexture(GL_TEXTURE0 + dwStage)); + if (!flags.bLoaded) Load () ; + else PostLoad () ; + bind (dwStage) ; +}; + +void CTexture::apply_theora(u32 dwStage) { + CHK_GL(glActiveTexture(GL_TEXTURE0 + dwStage)); + CHK_GL(glBindTexture(desc, pSurface)); + + if (pTheora->Update(m_play_time!=0xFFFFFFFF?m_play_time:Device.dwTimeContinual)) { + u32* pBits; + u32 _w = pTheora->Width(true); + u32 _h = pTheora->Height(true); + + // Clear and map buffer for writing + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pBuffer); + CHK_GL(glBufferData(GL_PIXEL_UNPACK_BUFFER, _w * _h * 4, 0, GL_STREAM_DRAW)); // Invalidate buffer + CHK_GL(pBits = (u32*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY)); + + // Write to the buffer and copy it to the texture + int _pos = 0; + pTheora->DecompressFrame(pBits, 0, _pos); + CHK_GL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)); + CHK_GL(glTexSubImage2D(desc, 0, 0, 0, _w, _h, GL_BGRA, GL_UNSIGNED_BYTE, 0)); + + // Unmap the buffer to restore normal texture functionality + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + } +}; +void CTexture::apply_avi(u32 dwStage) { + CHK_GL(glActiveTexture(GL_TEXTURE0 + dwStage)); + CHK_GL(glBindTexture(desc, pSurface)); + + if (pAVI->NeedUpdate()) { + // AVI + BYTE* ptr; pAVI->GetFrame(&ptr); + CHK_GL(glTexSubImage2D(desc, 0, 0, 0, m_width, m_height, + GL_RGBA, GL_UNSIGNED_BYTE, ptr)); + } +}; +void CTexture::apply_seq(u32 dwStage) { + // SEQ + u32 frame = Device.dwTimeContinual/seqMSPF; //Device.dwTimeGlobal + u32 frame_data = seqDATA.size(); + if (flags.seqCycles) { + u32 frame_id = frame%(frame_data*2); + if (frame_id>=frame_data) frame_id = (frame_data-1) - (frame_id%frame_data); + pSurface = seqDATA[frame_id]; + } else { + u32 frame_id = frame%frame_data; + pSurface = seqDATA[frame_id]; + } + + CHK_GL(glActiveTexture(GL_TEXTURE0 + dwStage)); + CHK_GL(glBindTexture(desc, pSurface)); +}; +void CTexture::apply_normal(u32 dwStage) { + CHK_GL(glActiveTexture(GL_TEXTURE0 + dwStage)); + CHK_GL(glBindTexture(desc, pSurface)); +}; + +void CTexture::Preload () +{ + m_bumpmap = DEV->m_textures_description.GetBumpName(cName); + m_material = DEV->m_textures_description.GetMaterial(cName); +} + +void CTexture::Load () +{ + flags.bLoaded = true; + desc_cache = 0; + if (pSurface) return; + + flags.bUser = false; + flags.MemoryUsage = 0; + if (0 == stricmp(*cName, "$null")) return; + if (0 != strstr(*cName, "$user$")) { + flags.bUser = true; + return; + } + + Preload(); + + bool bCreateView = true; + + // Check for OGM + string_path fn; + if (FS.exist(fn, "$game_textures$", *cName, ".ogm")) { + // AVI + pTheora = new CTheoraSurface(); + m_play_time = 0xFFFFFFFF; + + if (!pTheora->Load(fn)) + { + xr_delete(pTheora); + FATAL("Can't open video stream"); + } + else + { + flags.MemoryUsage = pTheora->Width(true)*pTheora->Height(true) * 4; + pTheora->Play(TRUE, Device.dwTimeContinual); + + // Now create texture + GLuint pTexture = 0; + u32 _w = pTheora->Width(false); + u32 _h = pTheora->Height(false); + + glGenBuffers(1, &pBuffer); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pBuffer); + CHK_GL(glBufferData(GL_PIXEL_UNPACK_BUFFER, flags.MemoryUsage, 0, GL_STREAM_DRAW)); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + glGenTextures(1, &pTexture); + glBindTexture(GL_TEXTURE_2D, pTexture); + CHK_GL(glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, _w, _h)); + + pSurface = pTexture; + desc = GL_TEXTURE_2D; + if (glGetError() != GL_NO_ERROR) + { + FATAL("Invalid video stream"); + xr_delete(pTheora); + pSurface = 0; + } + } + } + else if (FS.exist(fn, "$game_textures$", *cName, ".avi")) { + // AVI + pAVI = new CAviPlayerCustom(); + + if (!pAVI->Load(fn)) { + xr_delete(pAVI); + FATAL("Can't open video stream"); + } + else { + flags.MemoryUsage = pAVI->m_dwWidth*pAVI->m_dwHeight * 4; + + // Create pixel buffer object + glGenBuffers(1, &pBuffer); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pBuffer); + CHK_GL(glBufferData(GL_PIXEL_UNPACK_BUFFER, flags.MemoryUsage, 0, GL_STREAM_DRAW)); + + // Now create texture to copy PBO into + GLuint pTexture = 0; + glGenTextures(1, &pTexture); + glBindTexture(GL_TEXTURE_2D, pTexture); + CHK_GL(glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, pAVI->m_dwWidth, pAVI->m_dwHeight)); + + pSurface = pTexture; + desc = GL_TEXTURE_2D; + if (glGetError() != GL_NO_ERROR) + { + FATAL("Invalid video stream"); + xr_delete(pAVI); + pSurface = 0; + } + } + } + else if (FS.exist(fn, "$game_textures$", *cName, ".seq")) { + // Sequence + string256 buffer; + IReader* _fs = FS.r_open(fn); + + flags.seqCycles = FALSE; + _fs->r_string(buffer, sizeof(buffer)); + if (0 == stricmp(buffer, "cycled")) + { + flags.seqCycles = TRUE; + _fs->r_string(buffer, sizeof(buffer)); + } + u32 fps = atoi(buffer); + seqMSPF = 1000 / fps; + + while (!_fs->eof()) + { + _fs->r_string(buffer, sizeof(buffer)); + _Trim(buffer); + if (buffer[0]) + { + // Load another texture + u32 mem = 0; + pSurface = ::RImplementation.texture_load(buffer, mem, desc); + if (pSurface) + { + // pSurface->SetPriority (PRIORITY_LOW); + seqDATA.push_back(pSurface); + flags.MemoryUsage += mem; + } + } + } + pSurface = 0; + FS.r_close(_fs); + } + else { + // Normal texture + u32 mem = 0; + pSurface = ::RImplementation.texture_load(*cName, mem, desc); + + // Calc memory usage and preload into vid-mem + if (pSurface) { + // pSurface->SetPriority (PRIORITY_NORMAL); + flags.MemoryUsage = mem; + } + } + + PostLoad(); +} + +void CTexture::Unload () +{ +#ifdef DEBUG + string_path msg_buff; + sprintf_s(msg_buff, sizeof(msg_buff), "* Unloading texture [%s] pSurface ID=%d", cName.c_str(), pSurface); +#endif // DEBUG + + //. if (flags.bLoaded) Msg ("* Unloaded: %s",cName.c_str()); + + flags.bLoaded = FALSE; + if (!seqDATA.empty()) { + CHK_GL(glDeleteTextures(seqDATA.size(), seqDATA.data())); + seqDATA.clear(); + pSurface = 0; + } + + CHK_GL(glDeleteTextures(1, &pSurface)); + CHK_GL(glDeleteBuffers(1, &pBuffer)); + + xr_delete(pAVI); + xr_delete(pTheora); + + bind = fastdelegate::FastDelegate1(this, &CTexture::apply_load); +} + +void CTexture::desc_update() +{ + desc_cache = pSurface; + if (pSurface && (GL_TEXTURE_2D == desc)) + { + glBindTexture(desc, pSurface); + CHK_GL(glGetTexLevelParameteriv(desc, 0, GL_TEXTURE_WIDTH, &m_width)); + CHK_GL(glGetTexLevelParameteriv(desc, 0, GL_TEXTURE_HEIGHT, &m_height)); + } +} + +void CTexture::video_Play (BOOL looped, u32 _time) +{ + if (pTheora) pTheora->Play (looped,(_time!=0xFFFFFFFF)?(m_play_time=_time):Device.dwTimeContinual); +} + +void CTexture::video_Pause (BOOL state) +{ + if (pTheora) pTheora->Pause (state); +} + +void CTexture::video_Stop () +{ + if (pTheora) pTheora->Stop(); +} + +BOOL CTexture::video_IsPlaying () +{ + return (pTheora)?pTheora->IsPlaying():FALSE; +} diff --git a/src/Layers/xrRenderGL/glState.cpp b/src/Layers/xrRenderGL/glState.cpp new file mode 100644 index 00000000000..63d7b729788 --- /dev/null +++ b/src/Layers/xrRenderGL/glState.cpp @@ -0,0 +1,246 @@ +#include "stdafx.h" +#include "glState.h" + +glState::glState() +{ + // Clear the sampler array + memset(m_samplerArray, 0, CTexture::mtMaxCombinedShaderTextures * sizeof(GLuint)); + + m_pRasterizerState.CullMode = D3DCULL_CCW; + + m_pDepthStencilState.DepthEnable = TRUE; + m_pDepthStencilState.DepthFunc = D3DCMP_LESSEQUAL; + m_pDepthStencilState.DepthWriteMask = GL_TRUE; + m_pDepthStencilState.StencilEnable = TRUE; + m_pDepthStencilState.StencilFailOp = D3DSTENCILOP_KEEP; + m_pDepthStencilState.StencilDepthFailOp = D3DSTENCILOP_KEEP; + m_pDepthStencilState.StencilPassOp = D3DSTENCILOP_KEEP; + m_pDepthStencilState.StencilFunc = D3DCMP_ALWAYS; + m_pDepthStencilState.StencilMask = 0xFFFFFFFF; + m_pDepthStencilState.StencilWriteMask = 0xFFFFFFFF; + m_pDepthStencilState.StencilRef = 0; + + m_pBlendState.BlendEnable = TRUE; + m_pBlendState.SrcBlend = D3DBLEND_ONE; + m_pBlendState.DestBlend = D3DBLEND_ZERO; + m_pBlendState.SrcBlendAlpha = D3DBLEND_ONE; + m_pBlendState.DestBlendAlpha = D3DBLEND_ZERO; + m_pBlendState.BlendOp = D3DBLENDOP_ADD; + m_pBlendState.BlendOpAlpha = D3DBLENDOP_ADD; + m_pBlendState.ColorMask = 0xF; +} + +glState::~glState() +{ + Release(); +} + +// TODO: OGL: Does the render cache provide enough state management? +void glState::Apply() +{ + // TODO: OGL: Use glBindSamplers if ARB_multi_bind is supported. + for (size_t stage = 0; stage < CTexture::mtMaxCombinedShaderTextures; stage++) + { + if (m_samplerArray[stage]) + glBindSampler(stage, m_samplerArray[stage]); + } + + RCache.set_CullMode(m_pRasterizerState.CullMode); + RCache.set_Z(m_pDepthStencilState.DepthEnable); + RCache.set_ZFunc(m_pDepthStencilState.DepthFunc); + /* TODO: OGL: Cache the stencil state globally. + RCache.set_Stencil( + m_pDepthStencilState.StencilEnable, + m_pDepthStencilState.StencilFunc, + m_pDepthStencilState.StencilRef, + m_pDepthStencilState.StencilMask, + m_pDepthStencilState.StencilWriteMask, + m_pDepthStencilState.StencilFailOp, + m_pDepthStencilState.StencilPassOp, + m_pDepthStencilState.StencilDepthFailOp + );*/ + + CHK_GL(glDepthMask(m_pDepthStencilState.DepthWriteMask)); + + if (m_pBlendState.BlendEnable) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + + CHK_GL(glBlendFuncSeparate( + glStateUtils::ConvertBlendArg(m_pBlendState.SrcBlend), + glStateUtils::ConvertBlendArg(m_pBlendState.DestBlend), + glStateUtils::ConvertBlendArg(m_pBlendState.SrcBlendAlpha), + glStateUtils::ConvertBlendArg(m_pBlendState.DestBlendAlpha) + )); + CHK_GL(glBlendEquationSeparate( + glStateUtils::ConvertBlendOp(m_pBlendState.BlendOp), + glStateUtils::ConvertBlendOp(m_pBlendState.BlendOpAlpha) + )); + + // TODO: OGL: Cache the color mask globally. + //RCache.set_ColorWriteEnable(m_pBlendState.ColorMask); +} + +void glState::Release() +{ + // Delete any generated samplers in the array + CHK_GL(glDeleteSamplers(CTexture::mtMaxCombinedShaderTextures, m_samplerArray)); + + // Clear the sampler array + memset(m_samplerArray, 0, CTexture::mtMaxCombinedShaderTextures * sizeof(GLuint)); +} + +void glState::UpdateRenderState(u32 name, u32 value) +{ + switch (name) + { + case D3DRS_CULLMODE: + m_pRasterizerState.CullMode = (D3DCULL)value; + break; + + case D3DRS_ZENABLE: + m_pDepthStencilState.DepthEnable = value ? TRUE : FALSE; + break; + + case D3DRS_ZWRITEENABLE: + m_pDepthStencilState.DepthWriteMask = value ? GL_TRUE : GL_FALSE; + break; + + case D3DRS_ZFUNC: + m_pDepthStencilState.DepthFunc = (D3DCMPFUNC)value; + break; + + case D3DRS_STENCILENABLE: + m_pDepthStencilState.StencilEnable = value ? TRUE : FALSE; + break; + + case D3DRS_STENCILMASK: + m_pDepthStencilState.StencilMask = (UINT)value; + break; + + case D3DRS_STENCILWRITEMASK: + m_pDepthStencilState.StencilWriteMask = (UINT)value; + break; + + case D3DRS_STENCILFAIL: + m_pDepthStencilState.StencilFailOp = (D3DSTENCILOP)value; + break; + + case D3DRS_STENCILZFAIL: + m_pDepthStencilState.StencilDepthFailOp = (D3DSTENCILOP)value; + break; + + case D3DRS_STENCILPASS: + m_pDepthStencilState.StencilPassOp = (D3DSTENCILOP)value; + break; + + case D3DRS_STENCILFUNC: + m_pDepthStencilState.StencilFunc = (D3DCMPFUNC)value; + break; + + case D3DRS_STENCILREF: + m_pDepthStencilState.StencilRef = value; + break; + + case D3DRS_SRCBLEND: + m_pBlendState.SrcBlend = (D3DBLEND)value; + break; + + case D3DRS_DESTBLEND: + m_pBlendState.DestBlend = (D3DBLEND)value; + break; + + case D3DRS_BLENDOP: + m_pBlendState.BlendOp = (D3DBLENDOP)value; + break; + + case D3DRS_SRCBLENDALPHA: + m_pBlendState.SrcBlendAlpha = (D3DBLEND)value; + break; + + case D3DRS_DESTBLENDALPHA: + m_pBlendState.DestBlendAlpha = (D3DBLEND)value; + break; + + case D3DRS_BLENDOPALPHA: + m_pBlendState.BlendOpAlpha = (D3DBLENDOP)value; + break; + + case D3DRS_ALPHABLENDENABLE: + m_pBlendState.BlendEnable = value ? TRUE : FALSE; + break; + + case D3DRS_COLORWRITEENABLE: + case D3DRS_COLORWRITEENABLE1: + case D3DRS_COLORWRITEENABLE2: + case D3DRS_COLORWRITEENABLE3: + m_pBlendState.ColorMask = (UINT)value; + break; + + case D3DRS_LIGHTING: + case D3DRS_FOGENABLE: + case D3DRS_ALPHATESTENABLE: + case D3DRS_ALPHAREF: + // Deprecated + break; + + default: + VERIFY(!"Render state not implemented"); + break; + } +} + +void glState::UpdateSamplerState(u32 stage, u32 name, u32 value) +{ + if (stage < 0 || CTexture::mtMaxCombinedShaderTextures < stage) + return; + + GLint currentFilter = GL_NEAREST; + + if (m_samplerArray[stage] == NULL) + glGenSamplers (1, &m_samplerArray[stage]); + else if (name == D3DSAMP_MINFILTER || name == D3DSAMP_MIPFILTER) + glGetSamplerParameteriv(m_samplerArray[stage], GL_TEXTURE_MIN_FILTER, ¤tFilter); + + switch (name) + { + case D3DSAMP_ADDRESSU: /* D3DTEXTUREADDRESS for U coordinate */ + CHK_GL(glSamplerParameteri(m_samplerArray[stage], GL_TEXTURE_WRAP_S, glStateUtils::ConvertTextureAddressMode(value))); + break; + case D3DSAMP_ADDRESSV: /* D3DTEXTUREADDRESS for V coordinate */ + CHK_GL(glSamplerParameteri(m_samplerArray[stage], GL_TEXTURE_WRAP_T, glStateUtils::ConvertTextureAddressMode(value))); + break; + case D3DSAMP_ADDRESSW: /* D3DTEXTUREADDRESS for W coordinate */ + CHK_GL(glSamplerParameteri(m_samplerArray[stage], GL_TEXTURE_WRAP_R, glStateUtils::ConvertTextureAddressMode(value))); + break; + case D3DSAMP_BORDERCOLOR: /* D3DCOLOR */ + { + GLint color[] = { color_get_R(value), color_get_G(value), color_get_B(value), color_get_A(value) }; + CHK_GL(glSamplerParameteriv(m_samplerArray[stage], GL_TEXTURE_BORDER_COLOR, color)); + } + break; + case D3DSAMP_MAGFILTER: /* D3DTEXTUREFILTER filter to use for magnification */ + CHK_GL(glSamplerParameteri(m_samplerArray[stage], GL_TEXTURE_MAG_FILTER, glStateUtils::ConvertTextureFilter(value))); + break; + case D3DSAMP_MINFILTER: /* D3DTEXTUREFILTER filter to use for minification */ + CHK_GL(glSamplerParameteri(m_samplerArray[stage], GL_TEXTURE_MIN_FILTER, glStateUtils::ConvertTextureFilter(value, currentFilter))); + break; + case D3DSAMP_MIPFILTER: /* D3DTEXTUREFILTER filter to use between mipmaps during minification */ + CHK_GL(glSamplerParameteri(m_samplerArray[stage], GL_TEXTURE_MIN_FILTER, glStateUtils::ConvertTextureFilter(value, currentFilter, true))); + break; + case D3DSAMP_MIPMAPLODBIAS: /* float Mipmap LOD bias */ + CHK_GL(glSamplerParameterf(m_samplerArray[stage], GL_TEXTURE_LOD_BIAS, *((float*)value))); + break; + case D3DSAMP_MAXMIPLEVEL: /* DWORD 0..(n-1) LOD index of largest map to use (0 == largest) */ + CHK_GL(glSamplerParameteri(m_samplerArray[stage], GL_TEXTURE_MAX_LEVEL, value)); + break; + case D3DSAMP_MAXANISOTROPY: /* DWORD maximum anisotropy */ + CHK_GL(glSamplerParameteri(m_samplerArray[stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, value)); + break; + default: + // Assume this is an OpenGL sampler parameter + CHK_GL(glSamplerParameteri(m_samplerArray[stage], name, value)); + break; + } +} diff --git a/src/Layers/xrRenderGL/glState.h b/src/Layers/xrRenderGL/glState.h new file mode 100644 index 00000000000..b910d4d2c1c --- /dev/null +++ b/src/Layers/xrRenderGL/glState.h @@ -0,0 +1,55 @@ +#pragma once + +#include "../xrRender/SH_Texture.h" + +typedef struct +{ + D3DCULL CullMode; +} D3D_RASTERIZER_STATE; + +typedef struct +{ + BOOL DepthEnable; + GLboolean DepthWriteMask; + GLenum DepthFunc; + BOOL StencilEnable; + UINT StencilMask; + UINT StencilWriteMask; + D3DSTENCILOP StencilFailOp; + D3DSTENCILOP StencilDepthFailOp; + D3DSTENCILOP StencilPassOp; + D3DCMPFUNC StencilFunc; + UINT StencilRef; +} D3D_DEPTH_STENCIL_STATE; + +typedef struct +{ + BOOL BlendEnable; + D3DBLEND SrcBlend; + D3DBLEND DestBlend; + D3DBLENDOP BlendOp; + D3DBLEND SrcBlendAlpha; + D3DBLEND DestBlendAlpha; + D3DBLENDOP BlendOpAlpha; + UINT ColorMask; +} D3D_BLEND_STATE; + +class glState +{ +private: + D3D_RASTERIZER_STATE m_pRasterizerState; + D3D_DEPTH_STENCIL_STATE m_pDepthStencilState; + D3D_BLEND_STATE m_pBlendState; + + GLuint m_samplerArray[CTexture::mtMaxCombinedShaderTextures]; + +public: + glState(); + ~glState(); + + void Apply(); + void Release(); + + void UpdateRenderState(u32 name, u32 value); + void UpdateSamplerState(u32 stage, u32 name, u32 value); +}; diff --git a/src/Layers/xrRenderGL/glStateUtils.cpp b/src/Layers/xrRenderGL/glStateUtils.cpp new file mode 100644 index 00000000000..ce8946ff86f --- /dev/null +++ b/src/Layers/xrRenderGL/glStateUtils.cpp @@ -0,0 +1,189 @@ +#include "stdafx.h" +#include "glStateUtils.h" + +namespace glStateUtils +{ + +GLenum ConvertCullMode(u32 Mode) +{ + switch (Mode) + { + //case D3DCULL_NONE: + // return ; + case D3DCULL_CW: + return GL_BACK; + case D3DCULL_CCW: + return GL_FRONT; + default: + VERIFY(!"Unexpected cull mode!"); + return GL_FRONT_AND_BACK; + } +} + +GLenum ConvertCmpFunction(u32 Func) +{ + switch (Func) + { + case D3DCMP_NEVER: + return GL_NEVER; + case D3DCMP_LESS: + return GL_LESS; + case D3DCMP_EQUAL: + return GL_EQUAL; + case D3DCMP_LESSEQUAL: + return GL_LEQUAL; + case D3DCMP_GREATER: + return GL_GREATER; + case D3DCMP_NOTEQUAL: + return GL_NOTEQUAL; + case D3DCMP_GREATEREQUAL: + return GL_GEQUAL; + case D3DCMP_ALWAYS: + return GL_ALWAYS; + default: + VERIFY(!"ConvertCmpFunction can't convert argument!"); + return GL_ALWAYS; + } +} + +GLenum ConvertStencilOp(u32 Op) +{ + switch (Op) + { + case D3DSTENCILOP_KEEP: + return GL_KEEP; + case D3DSTENCILOP_ZERO: + return GL_ZERO; + case D3DSTENCILOP_REPLACE: + return GL_REPLACE; + case D3DSTENCILOP_INCRSAT: + return GL_INCR; + case D3DSTENCILOP_DECRSAT: + return GL_DECR; + case D3DSTENCILOP_INVERT: + return GL_INVERT; + case D3DSTENCILOP_INCR: + return GL_INCR_WRAP; + case D3DSTENCILOP_DECR: + return GL_DECR_WRAP; + default: + VERIFY(!"ConvertStencilOp can't convert argument!"); + return GL_KEEP; + } +} + +GLenum ConvertBlendArg(u32 Arg) +{ + switch (Arg) + { + case D3DBLEND_ZERO: + return GL_ZERO; + case D3DBLEND_ONE: + return GL_ONE; + case D3DBLEND_SRCCOLOR: + return GL_SRC_COLOR; + case D3DBLEND_INVSRCCOLOR: + return GL_ONE_MINUS_SRC_COLOR; + case D3DBLEND_SRCALPHA: + return GL_SRC_ALPHA; + case D3DBLEND_INVSRCALPHA: + return GL_ONE_MINUS_SRC_ALPHA; + case D3DBLEND_DESTALPHA: + return GL_DST_ALPHA; + case D3DBLEND_INVDESTALPHA: + return GL_ONE_MINUS_DST_ALPHA; + case D3DBLEND_DESTCOLOR: + return GL_DST_COLOR; + case D3DBLEND_INVDESTCOLOR: + return GL_ONE_MINUS_DST_COLOR; + case D3DBLEND_SRCALPHASAT: + return GL_SRC_ALPHA_SATURATE; + //case D3DBLEND_BOTHSRCALPHA: + // return ; + //case D3DBLEND_BOTHINVSRCALPHA: + // return ; + //case D3DBLEND_BLENDFACTOR: + // return ; + //case D3DBLEND_INVBLENDFACTOR: + // return ; + //case D3DBLEND_SRCCOLOR2: + // return ; + //case D3DBLEND_INVSRCCOLOR2: + // return ; + default: + VERIFY(!"ConvertBlendArg can't convert argument!"); + return GL_ONE; + } +} + +GLenum ConvertBlendOp(u32 Op) +{ + switch (Op) + { + case D3DBLENDOP_ADD: + return GL_FUNC_ADD; + case D3DBLENDOP_SUBTRACT: + return GL_FUNC_SUBTRACT; + case D3DBLENDOP_REVSUBTRACT: + return GL_FUNC_REVERSE_SUBTRACT; + case D3DBLENDOP_MIN: + return GL_MIN; + case D3DBLENDOP_MAX: + return GL_MAX; + default: + VERIFY(!"ConvertBlendOp can't convert argument!"); + return GL_FUNC_ADD; + } +} + +GLenum ConvertTextureAddressMode(u32 Mode) +{ + switch (Mode) + { + case D3DTADDRESS_WRAP: + return GL_REPEAT; + case D3DTADDRESS_MIRROR: + return GL_MIRRORED_REPEAT; + case D3DTADDRESS_CLAMP: + return GL_CLAMP_TO_EDGE; + case D3DTADDRESS_BORDER: + return GL_CLAMP_TO_BORDER; + //case D3DTADDRESS_MIRRORONCE: + // return ; + default: + VERIFY(!"ConvertTextureAddressMode can't convert argument!"); + return GL_CLAMP_TO_EDGE; + } +} + +GLenum ConvertTextureFilter(u32 dxFilter, u32 glFilter, bool MipMap) +{ + const int FilterLinear = 0x01; + const int MipFilterLinear = 0x02; + const int MipFilterEnable = 0x100; + + switch (dxFilter) + { + case D3DTEXF_NONE: + if (MipMap) + return (glFilter & ~MipFilterLinear) & ~MipFilterEnable; + VERIFY(!"D3DTEXF_NONE only supported with D3DSAMP_MIPFILTER"); + return glFilter; + case D3DTEXF_POINT: + if (MipMap) + return (glFilter & ~MipFilterLinear) | MipFilterEnable; + else + return glFilter & ~FilterLinear; + case D3DTEXF_LINEAR: + case D3DTEXF_ANISOTROPIC: + if (MipMap) + return (glFilter | MipFilterLinear) | MipFilterEnable; + else + return glFilter | FilterLinear; + default: + VERIFY(!"ConvertTextureFilter can't convert argument!"); + return glFilter; + } +} + +}; diff --git a/src/Layers/xrRenderGL/glStateUtils.h b/src/Layers/xrRenderGL/glStateUtils.h new file mode 100644 index 00000000000..1ab76e303d8 --- /dev/null +++ b/src/Layers/xrRenderGL/glStateUtils.h @@ -0,0 +1,16 @@ +#pragma once + +#ifdef USE_OGL + +namespace glStateUtils +{ + GLenum ConvertCullMode(u32 Mode); + GLenum ConvertCmpFunction(u32 Func); + GLenum ConvertStencilOp(u32 Op); + GLenum ConvertBlendArg(u32 Arg); + GLenum ConvertBlendOp(u32 Op); + GLenum ConvertTextureAddressMode(u32 Mode); + GLenum ConvertTextureFilter(u32 dxFilter, u32 glFilter = GL_NEAREST, bool MipMap = false); +}; + +#endif // USE_OGL diff --git a/src/Layers/xrRenderGL/glTextureUtils.cpp b/src/Layers/xrRenderGL/glTextureUtils.cpp new file mode 100644 index 00000000000..7a62043870f --- /dev/null +++ b/src/Layers/xrRenderGL/glTextureUtils.cpp @@ -0,0 +1,112 @@ +#include "stdafx.h" +#include "glTextureUtils.h" + +namespace glTextureUtils +{ +struct TextureFormatPairs +{ + D3DFORMAT m_dx9FMT; + GLenum m_glFMT; +}; + +TextureFormatPairs TextureFormatList[] = +{ + { D3DFMT_UNKNOWN, NULL }, + //D3DFMT_R8G8B8 Not available + { D3DFMT_A8R8G8B8, GL_RGBA8 }, // Not available + //D3DFMT_X8R8G8B8 Not available + // TODO: DX10: Remove. Need only for nullrt + //D3DFMT_R5G6B5 Not available + { D3DFMT_R5G6B5, GL_RGBA8 }, // Not available + //D3DFMT_X1R5G5B5 Not available + //D3DFMT_A1R5G5B5 Not available + //D3DFMT_A4R4G4B4 Not available + //D3DFMT_R3G3B2 Not available + //D3DFMT_A8 DXGI_FORMAT_A8_UNORM + //D3DFMT_A8R3G3B2 Not available + //D3DFMT_X4R4G4B4 Not available + //D3DFMT_A2B10G10R10 DXGI_FORMAT_R10G10B10A2 + { D3DFMT_A8B8G8R8, GL_RGBA8 }, + //D3DFMT_X8B8G8R8 Not available + { D3DFMT_G16R16, GL_RG16 }, + //D3DFMT_A2R10G10B10 Not available + { D3DFMT_A16B16G16R16, GL_RGBA16 }, + //D3DFMT_A8P8 Not available + //D3DFMT_P8 Not available + { D3DFMT_L8, GL_R8 }, // Note: Use .r swizzle in shader to duplicate red to other components to get D3D9 behavior. + //D3DFMT_A8L8 Not available + //D3DFMT_A4L4 Not available + { D3DFMT_V8U8, GL_RG8 }, + //D3DFMT_L6V5U5 Not available + //D3DFMT_X8L8V8U8 Not available + { D3DFMT_Q8W8V8U8, GL_RGBA8 }, + { D3DFMT_V16U16, GL_RG16 }, + //D3DFMT_W11V11U10 Not available + //D3DFMT_A2W10V10U10 Not available + //D3DFMT_UYVY Not available + //D3DFMT_R8G8_B8G8 DXGI_FORMAT_G8R8_G8B8_UNORM (in DX9 the data was scaled up by 255.0f, but this can be handled in shader code). + //D3DFMT_YUY2 Not available + //D3DFMT_G8R8_G8B8 DXGI_FORMAT_R8G8_B8G8_UNORM (in DX9 the data was scaled up by 255.0f, but this can be handled in shader code). + //D3DFMT_DXT1 DXGI_FORMAT_BC1_UNORM & DXGI_FORMAT_BC1_UNORM_SRGB + //D3DFMT_DXT2 DXGI_FORMAT_BC1_UNORM & DXGI_FORMAT_BC1_UNORM_SRGB Note: DXT1 and DXT2 are the same from an API/hardware perspective... only difference was 'premultiplied alpha', which can be tracked by an application and doesn't need a separate format. + //D3DFMT_DXT3 DXGI_FORMAT_BC2_UNORM & DXGI_FORMAT_BC2_UNORM_SRGB + //D3DFMT_DXT4 DXGI_FORMAT_BC2_UNORM & DXGI_FORMAT_BC2_UNORM_SRGB Note: DXT3 and DXT4 are the same from an API/hardware perspective... only difference was 'premultiplied alpha', which can be tracked by an application and doesn't need a separate format. + //D3DFMT_DXT5 DXGI_FORMAT_BC3_UNORM & DXGI_FORMAT_BC3_UNORM_SRGB + //D3DFMT_D16 GL_DEPTH_COMPONENT16 + //D3DFMT_D32 Not available + //D3DFMT_D15S1 Not available + //D3DFMT_D24S8 Not available + { D3DFMT_D24X8, GL_DEPTH24_STENCIL8 }, + //D3DFMT_D24X4S4 Not available + //D3DFMT_D16 DXGI_FORMAT_D16_UNORM + //{ D3DFMT_D32F_LOCKABLE, GL_DEPTH_COMPONENT32F }, + //D3DFMT_D24FS8 Not available + //D3DFMT_S1D15 Not available + //D3DFMT_S8D24 GL_DEPTH24_STENCIL8 + //D3DFMT_X8D24 Not available + //D3DFMT_X4S4D24 Not available + //D3DFMT_L16 DXGI_FORMAT_R16_UNORM Note: Use .r swizzle in shader to duplicate red to other components to get D3D9 behavior. + //D3DFMT_INDEX16 DXGI_FORMAT_R16_UINT + //D3DFMT_INDEX32 DXGI_FORMAT_R32_UINT + //D3DFMT_Q16W16V16U16 GL_RGBA16 + //D3DFMT_MULTI2_ARGB8 Not available + //D3DFMT_R16F GL_R16F + { D3DFMT_G16R16F, GL_RG16F }, + { D3DFMT_A16B16G16R16F, GL_RGBA16F }, + { D3DFMT_R32F, GL_R32F }, + { D3DFMT_R16F, GL_R16F }, + //{ D3DFMT_G32R32F, GL_RG32F }, + { D3DFMT_A32B32G32R32F, GL_RGBA32F }, + //D3DFMT_CxV8U8 Not available + //D3DDECLTYPE_FLOAT1 GL_R32F + //D3DDECLTYPE_FLOAT2 GL_RG32F + //D3DDECLTYPE_FLOAT3 GL_RGB32F + //D3DDECLTYPE_FLOAT4 GL_RGBA32F + //D3DDECLTYPED3DCOLOR Not available + //D3DDECLTYPE_UBYTE4 GL_RGBA8 Note: Shader gets UINT values, but if Direct3D 9 style integral floats are needed (0.0f, 1.0f... 255.f), UINT can just be converted to float32 in shader. + //D3DDECLTYPE_SHORT2 GL_RG16 Note: Shader gets SINT values, but if Direct3D 9 style integral floats are needed, SINT can just be converted to float32 in shader. + //D3DDECLTYPE_SHORT4 GL_RGBA16 Note: Shader gets SINT values, but if Direct3D 9 style integral floats are needed, SINT can just be converted to float32 in shader. + //D3DDECLTYPE_UBYTE4N GL_RGBA8 + //D3DDECLTYPE_SHORT2N GL_RG16 + //D3DDECLTYPE_SHORT4N GL_RGBA16 + //D3DDECLTYPE_USHORT2N GL_RG16 + //D3DDECLTYPE_USHORT4N GL_RGBA16 + //D3DDECLTYPE_UDEC3 Not available + //D3DDECLTYPE_DEC3N Not available + //D3DDECLTYPE_FLOAT16_2 GL_RG16 + //D3DDECLTYPE_FLOAT16_4 GL_RGBA16 +}; + +GLenum ConvertTextureFormat(D3DFORMAT dx9FMT) +{ + int arrayLength = sizeof(TextureFormatList)/sizeof(TextureFormatList[0]); + for (int i=0; itype); + Fvector4 it[4]; + switch (L.cls) + { + case RC_2x4: + it[0].set(A._11, A._21, A._31, A._41); + it[1].set(A._12, A._22, A._32, A._42); + CHK_GL(glProgramUniformMatrix4x2fv(L.program, L.location, 1, GL_TRUE, (float*)&it)); + break; + case RC_3x4: + it[0].set(A._11, A._21, A._31, A._41); + it[1].set(A._12, A._22, A._32, A._42); + it[2].set(A._13, A._23, A._33, A._43); + CHK_GL(glProgramUniformMatrix4x3fv(L.program, L.location, 1, GL_TRUE, (float*)&it)); + break; + case RC_4x4: + it[0].set(A._11, A._21, A._31, A._41); + it[1].set(A._12, A._22, A._32, A._42); + it[2].set(A._13, A._23, A._33, A._43); + it[3].set(A._14, A._24, A._34, A._44); + CHK_GL(glProgramUniformMatrix4fv(L.program, L.location, 1, GL_TRUE, (float*)&it)); + break; + default: +#ifdef DEBUG + xrDebug::Fatal(DEBUG_INFO, "Invalid constant run-time-type for '%s'", *C->name); +#else + NODEFAULT; +#endif + } + } + ICF void set(R_constant* C, R_constant_load& L, const Fvector4& A) { + VERIFY(RC_float == C->type); + switch (L.cls) + { + case RC_1x2: + CHK_GL(glProgramUniform2fv(L.program, L.location, 1, (float*)&A)); + break; + case RC_1x3: + CHK_GL(glProgramUniform3fv(L.program, L.location, 1, (float*)&A)); + break; + case RC_1x4: + CHK_GL(glProgramUniform4fv(L.program, L.location, 1, (float*)&A)); + break; + default: +#ifdef DEBUG + xrDebug::Fatal(DEBUG_INFO, "Invalid constant run-time-type for '%s'", *C->name); +#else + NODEFAULT; +#endif + } + } + ICF void set(R_constant* C, R_constant_load& L, float x, float y, float z, float w) { + VERIFY(RC_float == C->type); + switch (L.cls) + { + case RC_1x2: + CHK_GL(glProgramUniform2f(L.program, L.location, x, y)); + break; + case RC_1x3: + CHK_GL(glProgramUniform3f(L.program, L.location, x, y, z)); + break; + case RC_1x4: + CHK_GL(glProgramUniform4f(L.program, L.location, x, y, z, w)); + break; + default: +#ifdef DEBUG + xrDebug::Fatal(DEBUG_INFO, "Invalid constant run-time-type for '%s'", *C->name); +#else + NODEFAULT; +#endif + } + } + + // scalars, non-array versions + ICF void set(R_constant* C, R_constant_load& L, float A) + { + VERIFY(RC_float == C->type); + VERIFY(RC_1x1 == L.cls); + CHK_GL(glProgramUniform1f(L.program, L.location, A)); + } + ICF void set(R_constant* C, R_constant_load& L, int A) + { + VERIFY(RC_int == C->type); + VERIFY(RC_1x1 == L.cls); + CHK_GL(glProgramUniform1i(L.program, L.location, A)); + } + +public: + // fp, non-array versions + ICF void set (R_constant* C, const Fmatrix& A) { + if (C->destination&RC_dest_pixel) { set(C, C->ps, A); } + if (C->destination&RC_dest_vertex) { set(C, C->vs, A); } + } + ICF void set (R_constant* C, const Fvector4& A) { + if (C->destination&RC_dest_pixel) { set(C, C->ps, A); } + if (C->destination&RC_dest_vertex) { set(C, C->vs, A); } + } + ICF void set (R_constant* C, float x, float y, float z, float w) { + if (C->destination&RC_dest_pixel) { set(C, C->ps, x, y, z, w); } + if (C->destination&RC_dest_vertex) { set(C, C->vs, x, y, z, w); } + } + + // scalars, non-array versions + ICF void set(R_constant* C, float A) + { + if (C->destination&RC_dest_pixel) { set(C, C->ps, A); } + if (C->destination&RC_dest_vertex) { set(C, C->vs, A); } + } + ICF void set(R_constant* C, int A) + { + if (C->destination&RC_dest_pixel) { set(C, C->ps, A); } + if (C->destination&RC_dest_vertex) { set(C, C->vs, A); } + } + + // fp, array versions + ICF void seta (R_constant* C, u32 e, const Fmatrix& A) { + R_constant_load L; + if (C->destination&RC_dest_pixel) { L = C->ps; } + if (C->destination&RC_dest_vertex) { L = C->vs; } + L.location += e; + set(C, L, A); + } + ICF void seta (R_constant* C, u32 e, const Fvector4& A) { + R_constant_load L; + if (C->destination&RC_dest_pixel) { L = C->ps; } + if (C->destination&RC_dest_vertex) { L = C->vs; } + L.location += e; + set(C, L, A); + } + ICF void seta (R_constant* C, u32 e, float x, float y, float z, float w) { + R_constant_load L; + if (C->destination&RC_dest_pixel) { L = C->ps; } + if (C->destination&RC_dest_vertex) { L = C->vs; } + L.location += e; + set(C, L, x, y, z, w); + + } + + // TODO: OGL: Implement constant caching through UBOs + ICF void flush () + { + } +}; +#endif // glr_constants_cacheH diff --git a/src/Layers/xrRenderPC_GL/GLUtils.cpp b/src/Layers/xrRenderPC_GL/GLUtils.cpp new file mode 100644 index 00000000000..c9fafa5f995 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/GLUtils.cpp @@ -0,0 +1,4 @@ +#include "stdafx.h" +#include "GLUtils.h" + +CDrawUtilities DUImpl; diff --git a/src/Layers/xrRenderPC_GL/GLUtils.h b/src/Layers/xrRenderPC_GL/GLUtils.h new file mode 100644 index 00000000000..ca6f604f9d5 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/GLUtils.h @@ -0,0 +1,66 @@ +#pragma once +#include "..\..\Include\xrRender\DrawUtils.h" + +class ECORE_API CDrawUtilities : + public CDUInterface +{ +public: + CDrawUtilities() { } + + //---------------------------------------------------- + virtual void __stdcall DrawCross(const Fvector& p, float szx1, float szy1, float szz1, float szx2, float szy2, float szz2, u32 clr, BOOL bRot45 = false) { VERIFY(!"CDrawUtilities::DrawCross not implemented."); }; + virtual void __stdcall DrawCross(const Fvector& p, float sz, u32 clr, BOOL bRot45 = false) { VERIFY(!"CDrawUtilities::DrawCross not implemented."); }; + virtual void __stdcall DrawFlag(const Fvector& p, float heading, float height, float sz, float sz_fl, u32 clr, BOOL bDrawEntity) { VERIFY(!"CDrawUtilities::DrawFlag not implemented."); }; + virtual void __stdcall DrawRomboid(const Fvector& p, float radius, u32 clr) { VERIFY(!"CDrawUtilities::DrawRomboid not implemented."); }; + virtual void __stdcall DrawJoint(const Fvector& p, float radius, u32 clr) { VERIFY(!"CDrawUtilities::DrawJoint not implemented."); }; + + virtual void __stdcall DrawSpotLight(const Fvector& p, const Fvector& d, float range, float phi, u32 clr) { VERIFY(!"CDrawUtilities::DrawSpotLight not implemented."); }; + virtual void __stdcall DrawDirectionalLight(const Fvector& p, const Fvector& d, float radius, float range, u32 clr) { VERIFY(!"CDrawUtilities::DrawDirectionalLight not implemented."); }; + virtual void __stdcall DrawPointLight(const Fvector& p, float radius, u32 clr) { VERIFY(!"CDrawUtilities::DrawPointLight not implemented."); }; + + virtual void __stdcall DrawSound(const Fvector& p, float radius, u32 clr) { VERIFY(!"CDrawUtilities::DrawSound not implemented."); }; + virtual void __stdcall DrawLineSphere(const Fvector& p, float radius, u32 clr, BOOL bCross) { VERIFY(!"CDrawUtilities::DrawLineSphere not implemented."); }; + + virtual void __stdcall dbgDrawPlacement(const Fvector& p, int sz, u32 clr, LPCSTR caption = 0, u32 clr_font = 0xffffffff) { VERIFY(!"CDrawUtilities::dbgDrawPlacement not implemented."); }; + virtual void __stdcall dbgDrawVert(const Fvector& p0, u32 clr, LPCSTR caption = 0) { VERIFY(!"CDrawUtilities::dbgDrawVert not implemented."); }; + virtual void __stdcall dbgDrawEdge(const Fvector& p0, const Fvector& p1, u32 clr, LPCSTR caption = 0) { VERIFY(!"CDrawUtilities::dbgDrawEdge not implemented."); }; + virtual void __stdcall dbgDrawFace(const Fvector& p0, const Fvector& p1, const Fvector& p2, u32 clr, LPCSTR caption = 0) { VERIFY(!"CDrawUtilities::dbgDrawFace not implemented."); }; + + virtual void __stdcall DrawFace(const Fvector& p0, const Fvector& p1, const Fvector& p2, u32 clr_s, u32 clr_w, BOOL bSolid, BOOL bWire) { VERIFY(!"CDrawUtilities::DrawFace not implemented."); }; + virtual void __stdcall DrawLine(const Fvector& p0, const Fvector& p1, u32 clr) { VERIFY(!"CDrawUtilities::DrawLine not implemented."); }; + virtual void __stdcall DrawLink(const Fvector& p0, const Fvector& p1, float sz, u32 clr) { VERIFY(!"CDrawUtilities::DrawLink not implemented."); }; + virtual void __stdcall DrawFaceNormal(const Fvector& p0, const Fvector& p1, const Fvector& p2, float size, u32 clr) { VERIFY(!"CDrawUtilities::DrawFaceNormal not implemented."); }; + virtual void __stdcall DrawFaceNormal(const Fvector* p, float size, u32 clr) { VERIFY(!"CDrawUtilities::DrawFaceNormal not implemented."); }; + virtual void __stdcall DrawFaceNormal(const Fvector& C, const Fvector& N, float size, u32 clr) { VERIFY(!"CDrawUtilities::DrawFaceNormal not implemented."); }; + virtual void __stdcall DrawSelectionBox(const Fvector& center, const Fvector& size, u32* c = 0) { VERIFY(!"CDrawUtilities::DrawSelectionBox not implemented."); }; + virtual void __stdcall DrawSelectionBox(const Fbox& box, u32* c = 0) { VERIFY(!"CDrawUtilities::DrawSelectionBox not implemented."); }; + virtual void __stdcall DrawIdentSphere(BOOL bSolid, BOOL bWire, u32 clr_s, u32 clr_w) { VERIFY(!"CDrawUtilities::DrawIdentSphere not implemented."); }; + virtual void __stdcall DrawIdentSpherePart(BOOL bSolid, BOOL bWire, u32 clr_s, u32 clr_w) { VERIFY(!"CDrawUtilities::DrawIdentSpherePart not implemented."); }; + virtual void __stdcall DrawIdentCone(BOOL bSolid, BOOL bWire, u32 clr_s, u32 clr_w) { VERIFY(!"CDrawUtilities::DrawIdentCone not implemented."); }; + virtual void __stdcall DrawIdentCylinder(BOOL bSolid, BOOL bWire, u32 clr_s, u32 clr_w) { VERIFY(!"CDrawUtilities::DrawIdentCylinder not implemented."); }; + virtual void __stdcall DrawIdentBox(BOOL bSolid, BOOL bWire, u32 clr_s, u32 clr_w) { VERIFY(!"CDrawUtilities::DrawIdentBox not implemented."); }; + + virtual void __stdcall DrawBox(const Fvector& offs, const Fvector& Size, BOOL bSolid, BOOL bWire, u32 clr_s, u32 clr_w) { VERIFY(!"CDrawUtilities::DrawBox not implemented."); }; + virtual void __stdcall DrawAABB(const Fvector& p0, const Fvector& p1, u32 clr_s, u32 clr_w, BOOL bSolid, BOOL bWire) { VERIFY(!"CDrawUtilities::DrawAABB not implemented."); }; + virtual void __stdcall DrawAABB(const Fmatrix& parent, const Fvector& center, const Fvector& size, u32 clr_s, u32 clr_w, BOOL bSolid, BOOL bWire) { VERIFY(!"CDrawUtilities::DrawAABB not implemented."); }; + virtual void __stdcall DrawOBB(const Fmatrix& parent, const Fobb& box, u32 clr_s, u32 clr_w) { VERIFY(!"CDrawUtilities::DrawOBB not implemented."); }; + virtual void __stdcall DrawSphere(const Fmatrix& parent, const Fvector& center, float radius, u32 clr_s, u32 clr_w, BOOL bSolid, BOOL bWire) { VERIFY(!"CDrawUtilities::DrawSphere not implemented."); }; + virtual void __stdcall DrawSphere(const Fmatrix& parent, const Fsphere& S, u32 clr_s, u32 clr_w, BOOL bSolid, BOOL bWire) { VERIFY(!"CDrawUtilities::DrawSphere not implemented."); }; + virtual void __stdcall DrawCylinder(const Fmatrix& parent, const Fvector& center, const Fvector& dir, float height, float radius, u32 clr_s, u32 clr_w, BOOL bSolid, BOOL bWire) { VERIFY(!"CDrawUtilities::DrawCylinder not implemented."); }; + virtual void __stdcall DrawCone(const Fmatrix& parent, const Fvector& apex, const Fvector& dir, float height, float radius, u32 clr_s, u32 clr_w, BOOL bSolid, BOOL bWire) { VERIFY(!"CDrawUtilities::DrawCone not implemented."); }; + virtual void __stdcall DrawPlane(const Fvector& center, const Fvector2& scale, const Fvector& rotate, u32 clr_s, u32 clr_w, BOOL bCull, BOOL bSolid, BOOL bWire) { VERIFY(!"CDrawUtilities::DrawPlane not implemented."); }; + virtual void __stdcall DrawPlane(const Fvector& p, const Fvector& n, const Fvector2& scale, u32 clr_s, u32 clr_w, BOOL bCull, BOOL bSolid, BOOL bWire) { VERIFY(!"CDrawUtilities::DrawPlane not implemented."); }; + virtual void __stdcall DrawRectangle(const Fvector& o, const Fvector& u, const Fvector& v, u32 clr_s, u32 clr_w, BOOL bSolid, BOOL bWire) { VERIFY(!"CDrawUtilities::DrawRectangle not implemented."); }; + + virtual void __stdcall DrawGrid() { VERIFY(!"CDrawUtilities::DrawGrid not implemented."); }; + virtual void __stdcall DrawPivot(const Fvector& pos, float sz = 5.f) { VERIFY(!"CDrawUtilities::DrawPivot not implemented."); }; + virtual void __stdcall DrawAxis(const Fmatrix& T) { VERIFY(!"CDrawUtilities::DrawAxis not implemented."); }; + virtual void __stdcall DrawObjectAxis(const Fmatrix& T, float sz, BOOL sel) { VERIFY(!"CDrawUtilities::DrawObjectAxis not implemented."); }; + virtual void __stdcall DrawSelectionRect(const Ivector2& m_SelStart, const Ivector2& m_SelEnd) { VERIFY(!"CDrawUtilities::DrawSelectionRect not implemented."); }; + + virtual void __stdcall OutText(const Fvector& pos, LPCSTR text, u32 color = 0xFF000000, u32 shadow_color = 0xFF909090) { VERIFY(!"CDrawUtilities::OutText not implemented."); }; + + virtual void __stdcall OnDeviceDestroy() { VERIFY(!"CDrawUtilities::OnDeviceDestroy not implemented."); }; +}; + +extern ECORE_API CDrawUtilities DUImpl; diff --git a/src/Layers/xrRenderPC_GL/GL_DStreams.cpp b/src/Layers/xrRenderPC_GL/GL_DStreams.cpp new file mode 100644 index 00000000000..3464acd41b0 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/GL_DStreams.cpp @@ -0,0 +1,192 @@ +#include "stdafx.h" +#pragma hdrstop + +#include "../xrRender/ResourceManager.h" +#include "../xrRender/R_DStreams.h" + +#include "glRenderDeviceRender.h" +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +int rsDVB_Size = 512 + 1024; +int rsDIB_Size = 512; + +void _VertexStream::Create() +{ + //glRenderDeviceRender::Instance().Resources->Evict (); + DEV->Evict(); + + mSize = rsDVB_Size * 1024; + glGenBuffers(1, &pVB); + R_ASSERT(pVB); + + glBindBuffer(GL_ARRAY_BUFFER, pVB); + CHK_GL(glBufferData(GL_ARRAY_BUFFER, mSize, nullptr, GL_DYNAMIC_DRAW)); + + mPosition = 0; + mDiscardID = 0; + + Msg("* DVB created: %dK", mSize / 1024); +} + +void _VertexStream::Destroy() +{ + glDeleteBuffers(1, &pVB); + _clear(); +} + +void* _VertexStream::Lock(u32 vl_Count, u32 Stride, u32& vOffset) +{ +#ifdef DEBUG + PGO(Msg("PGO:VB_LOCK:%d", vl_Count)); + VERIFY(0 == dbg_lock); + dbg_lock++; +#endif + + // Ensure there is enough space in the VB for this data + u32 bytes_need = vl_Count*Stride; + R_ASSERT2((bytes_need <= mSize) && vl_Count, make_string("bytes_need = %d, mSize = %d, vl_Count = %d", bytes_need, mSize, vl_Count)); + + // Vertex-local info + u32 vl_mSize = mSize / Stride; + u32 vl_mPosition = mPosition / Stride; + + // Check if there is need to flush and perform lock + void* pData = nullptr; + glBindBuffer(GL_ARRAY_BUFFER, pVB); + if ((vl_Count + vl_mPosition) >= vl_mSize) + { + // FLUSH-LOCK + mPosition = 0; + vOffset = 0; + mDiscardID++; + + CHK_GL(pData = glMapBufferRange(GL_ARRAY_BUFFER, mPosition, bytes_need, LOCKFLAGS_FLUSH)); + } + else { + // APPEND-LOCK + mPosition = vl_mPosition*Stride; + vOffset = vl_mPosition; + + CHK_GL(pData = glMapBufferRange(GL_ARRAY_BUFFER, mPosition, bytes_need, LOCKFLAGS_APPEND)); + } + VERIFY(pData); + + return pData; +} + +void _VertexStream::Unlock(u32 Count, u32 Stride) +{ +#ifdef DEBUG + PGO(Msg("PGO:VB_UNLOCK:%d", Count)); + VERIFY(1 == dbg_lock); + dbg_lock--; +#endif + mPosition += Count*Stride; + + VERIFY(pVB); + CHK_GL(glUnmapBuffer(GL_ARRAY_BUFFER)); +} + +void _VertexStream::reset_begin() +{ + old_pVB = pVB; + Destroy(); +} +void _VertexStream::reset_end() +{ + Create(); + //old_pVB = NULL; +} + +_VertexStream::_VertexStream() +{ + _clear(); +}; + +void _VertexStream::_clear() +{ + pVB = NULL; + mSize = 0; + mPosition = 0; + mDiscardID = 0; +#ifdef DEBUG + dbg_lock = 0; +#endif +} + +////////////////////////////////////////////////////////////////////////// +void _IndexStream::Create() +{ + //dxRenderDeviceRender::Instance().Resources->Evict (); + DEV->Evict(); + + mSize = rsDIB_Size * 1024; + glGenBuffers(1, &pIB); + R_ASSERT(pIB); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIB); + CHK_GL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, mSize, nullptr, GL_DYNAMIC_DRAW)); + + mPosition = 0; + mDiscardID = 0; + + Msg("* DIB created: %dK", mSize / 1024); +} + +void _IndexStream::Destroy() +{ + glDeleteBuffers(1, &pIB); + _clear(); +} + +u16* _IndexStream::Lock(u32 Count, u32& vOffset) +{ + PGO(Msg("PGO:IB_LOCK:%d", Count)); + vOffset = 0; + void* pLockedData = nullptr; + + // Ensure there is enough space in the VB for this data + R_ASSERT((2 * Count <= mSize) && Count); + + // If either user forced us to flush, + // or there is not enough space for the index data, + // then flush the buffer contents + GLbitfield flags = LOCKFLAGS_APPEND; + if (2 * (Count + mPosition) >= mSize) + { + mPosition = 0; // clear position + flags = LOCKFLAGS_FLUSH; // discard its contens + mDiscardID++; + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIB); + CHK_GL(pLockedData = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, mPosition * 2, Count * 2, flags)); + VERIFY(pLockedData); + + vOffset = mPosition; + + return LPWORD(pLockedData); +} + +void _IndexStream::Unlock(u32 RealCount) +{ + PGO(Msg("PGO:IB_UNLOCK:%d", RealCount)); + mPosition += RealCount; + VERIFY(pIB); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIB); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); +} + +void _IndexStream::reset_begin() +{ + old_pIB = pIB; + Destroy(); +} +void _IndexStream::reset_end() +{ + Create(); + //old_pIB = NULL; +} diff --git a/src/Layers/xrRenderPC_GL/SMAP_Allocator.h b/src/Layers/xrRenderPC_GL/SMAP_Allocator.h new file mode 100644 index 00000000000..758ba2c9cdf --- /dev/null +++ b/src/Layers/xrRenderPC_GL/SMAP_Allocator.h @@ -0,0 +1,85 @@ +#pragma once + +struct SMAP_Rect +{ + Ivector2 min,max; + bool intersect (SMAP_Rect& R) { + if( max.x < R.min.x ) return false; + if( max.y < R.min.y ) return false; + if( min.x > R.max.x ) return false; + if( min.y > R.max.y ) return false; + return true; + } + bool valid () { + if (min.x==max.x) return false; + if (min.y==max.y) return false; + return true; + } + void setup (Ivector2& p, u32 size) { + min = max = p; + max.add (size-1); + } + void get_cp (Ivector2& p0, Ivector2& p1) { + p0.set (max.x+1,min.y); // right + p1.set (min.x,max.y+1); // down + } +}; + +class SMAP_Allocator +{ + u32 psize; // pool size + xr_vector stack; // + xr_vector cpoint; // critical points +private: + void _add (SMAP_Rect& R) + { + stack.push_back (R); + Ivector2 p0,p1; + R.get_cp (p0,p1); + s32 ps = s32(psize); + if ((p0.x4); + + // setup first in the soup, if empty state + if (stack.empty()) { + Ivector2 p; p.set(0,0); + R.setup (p,_size); + _add (R); + return true; + } + + // perform search (first-fit) + for (u32 it=0; it=int(psize)) continue; + if (R.max.y>=int(psize)) continue; + BOOL bIntersect = false; + for (u32 t=0; t real), volumetric (usually after blend) + C.r_Pass ("accum_volume", "copy_p", false, FALSE,FALSE); + C.r_Sampler_rtf ("s_base", r2_RT_accum_temp ); + C.r_End (); + break; + case SE_MASK_ACCUM_2D: // copy accumulator (temp -> real), 2D (usually after sun-blend) + C.r_Pass ("stub_notransform_t", "copy", false, FALSE,FALSE); + C.r_Sampler_rtf ("s_base", r2_RT_accum_temp ); + C.r_End (); + break; + case SE_MASK_ALBEDO: // copy accumulator, 2D (for accum->color, albedo_wo) + C.r_Pass ("stub_notransform_t", "copy", false, FALSE,FALSE); + C.r_Sampler_rtf ("s_base", r2_RT_accum ); + C.r_End (); + break; + } +} \ No newline at end of file diff --git a/src/Layers/xrRenderPC_GL/blender_light_mask.h b/src/Layers/xrRenderPC_GL/blender_light_mask.h new file mode 100644 index 00000000000..6cdd6591fa7 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_light_mask.h @@ -0,0 +1,14 @@ +#pragma once + +class CBlender_accum_direct_mask : public IBlender +{ +public: + virtual LPCSTR getComment() { return "INTERNAL: mask direct light"; } + virtual BOOL canBeDetailed() { return FALSE; } + virtual BOOL canBeLMAPped() { return FALSE; } + + virtual void Compile (CBlender_Compile& C); + + CBlender_accum_direct_mask(); + virtual ~CBlender_accum_direct_mask(); +}; diff --git a/src/Layers/xrRenderPC_GL/blender_light_occq.cpp b/src/Layers/xrRenderPC_GL/blender_light_occq.cpp new file mode 100644 index 00000000000..4817195cbc7 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_light_occq.cpp @@ -0,0 +1,24 @@ +#include "stdafx.h" +#pragma hdrstop + +#include "Blender_light_occq.h" + +CBlender_light_occq::CBlender_light_occq () { description.CLS = 0; } +CBlender_light_occq::~CBlender_light_occq () { } + +void CBlender_light_occq::Compile(CBlender_Compile& C) +{ + IBlender::Compile (C); + + switch (C.iElement) + { + case 0: // occlusion testing + C.r_Pass ("dumb", "dumb",false,TRUE,FALSE,FALSE); + C.r_End (); + break; + case 1: // NV40 optimization :) + C.r_Pass ("stub_notransform_t", "dumb",false,FALSE,FALSE,FALSE); + C.r_End (); + break; + } +} diff --git a/src/Layers/xrRenderPC_GL/blender_light_occq.h b/src/Layers/xrRenderPC_GL/blender_light_occq.h new file mode 100644 index 00000000000..a0ae169816b --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_light_occq.h @@ -0,0 +1,14 @@ +#pragma once + +class CBlender_light_occq : public IBlender +{ +public: + virtual LPCSTR getComment() { return "INTERNAL: occlusion testing"; } + virtual BOOL canBeDetailed() { return FALSE; } + virtual BOOL canBeLMAPped() { return FALSE; } + + virtual void Compile (CBlender_Compile& C); + + CBlender_light_occq(); + virtual ~CBlender_light_occq(); +}; diff --git a/src/Layers/xrRenderPC_GL/blender_light_point.cpp b/src/Layers/xrRenderPC_GL/blender_light_point.cpp new file mode 100644 index 00000000000..449abe5fa19 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_light_point.cpp @@ -0,0 +1,67 @@ +#include "stdafx.h" +#pragma hdrstop + +#include "Blender_light_point.h" + +CBlender_accum_point::CBlender_accum_point () { description.CLS = 0; } +CBlender_accum_point::~CBlender_accum_point () { } + +void CBlender_accum_point::Compile(CBlender_Compile& C) +{ + IBlender::Compile (C); + + BOOL b_HW_smap = RImplementation.o.HW_smap; + BOOL b_HW_PCF = RImplementation.o.HW_smap_PCF; + BOOL blend = RImplementation.o.fp16_blend; + D3DBLEND dest = blend?D3DBLEND_ONE:D3DBLEND_ZERO; + switch (C.iElement) + { + case SE_L_FILL: // fill projective + C.r_Pass ("stub_notransform", "copy", false, FALSE, FALSE); + C.r_Sampler ("s_base", C.L_textures[0] ); + C.r_End (); + break; + case SE_L_UNSHADOWED: // unshadowed + C.r_Pass ("accum_volume", "accum_omni_unshadowed", false, FALSE,FALSE,blend,D3DBLEND_ONE,dest); + C.r_Sampler_rtf ("s_position", r2_RT_P ); + C.r_Sampler_rtf ("s_normal", r2_RT_N ); + C.r_Sampler_clw ("s_material", r2_material ); + C.r_Sampler_clf ("s_lmap", *C.L_textures[0]); + C.r_Sampler_rtf ("s_accumulator", r2_RT_accum ); + C.r_End (); + break; + case SE_L_NORMAL: // normal + C.r_Pass ("accum_volume", "accum_omni_normal", false, FALSE,FALSE,blend,D3DBLEND_ONE,dest); + C.r_Sampler_rtf ("s_position", r2_RT_P); + C.r_Sampler_rtf ("s_normal", r2_RT_N); + C.r_Sampler_clw ("s_material", r2_material); + C.r_Sampler ("s_lmap", C.L_textures[0] ); + C.r_Sampler_cmp ("s_smap", r2_RT_smap_depth); + jitter (C); + C.r_Sampler_rtf ("s_accumulator", r2_RT_accum ); + C.r_End (); + break; + case SE_L_FULLSIZE: // normal-fullsize + C.r_Pass ("accum_volume", "accum_omni_normal", false, FALSE,FALSE,blend,D3DBLEND_ONE,dest); + C.r_Sampler_rtf ("s_position", r2_RT_P); + C.r_Sampler_rtf ("s_normal", r2_RT_N); + C.r_Sampler_clw ("s_material", r2_material); + C.r_Sampler ("s_lmap", C.L_textures[0]); + C.r_Sampler_cmp ("s_smap", r2_RT_smap_depth); + jitter (C); + C.r_Sampler_rtf ("s_accumulator", r2_RT_accum ); + C.r_End (); + break; + case SE_L_TRANSLUENT: // shadowed + transluency + C.r_Pass ("accum_volume", "accum_omni_transluent", false, FALSE,FALSE,blend,D3DBLEND_ONE,dest); + C.r_Sampler_rtf ("s_position", r2_RT_P); + C.r_Sampler_rtf ("s_normal", r2_RT_N); + C.r_Sampler_clw ("s_material", r2_material); + C.r_Sampler_clf ("s_lmap", r2_RT_smap_surf); // diff here + C.r_Sampler_cmp ("s_smap", r2_RT_smap_depth); + jitter (C); + C.r_Sampler_rtf ("s_accumulator", r2_RT_accum ); + C.r_End (); + break; + } +} diff --git a/src/Layers/xrRenderPC_GL/blender_light_point.h b/src/Layers/xrRenderPC_GL/blender_light_point.h new file mode 100644 index 00000000000..ceb641a5bce --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_light_point.h @@ -0,0 +1,14 @@ +#pragma once + +class CBlender_accum_point : public IBlender +{ +public: + virtual LPCSTR getComment() { return "INTERNAL: accumulate point light"; } + virtual BOOL canBeDetailed() { return FALSE; } + virtual BOOL canBeLMAPped() { return FALSE; } + + virtual void Compile (CBlender_Compile& C); + + CBlender_accum_point(); + virtual ~CBlender_accum_point(); +}; diff --git a/src/Layers/xrRenderPC_GL/blender_light_reflected.cpp b/src/Layers/xrRenderPC_GL/blender_light_reflected.cpp new file mode 100644 index 00000000000..bde6d658d65 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_light_reflected.cpp @@ -0,0 +1,21 @@ +#include "stdafx.h" +#pragma hdrstop + +#include "Blender_light_reflected.h" + +CBlender_accum_reflected::CBlender_accum_reflected () { description.CLS = 0; } +CBlender_accum_reflected::~CBlender_accum_reflected () { } + +void CBlender_accum_reflected::Compile(CBlender_Compile& C) +{ + IBlender::Compile (C); + BOOL blend = RImplementation.o.fp16_blend; + D3DBLEND dest = blend?D3DBLEND_ONE:D3DBLEND_ZERO; + + C.r_Pass ("accum_volume", "accum_indirect",false, FALSE,FALSE,blend,D3DBLEND_ONE,dest); + C.r_Sampler_rtf ("s_position", r2_RT_P); + C.r_Sampler_rtf ("s_normal", r2_RT_N); + C.r_Sampler_clw ("s_material", r2_material); + C.r_Sampler_rtf ("s_accumulator", r2_RT_accum ); + C.r_End (); +} diff --git a/src/Layers/xrRenderPC_GL/blender_light_reflected.h b/src/Layers/xrRenderPC_GL/blender_light_reflected.h new file mode 100644 index 00000000000..148e3283c97 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_light_reflected.h @@ -0,0 +1,14 @@ +#pragma once + +class CBlender_accum_reflected : public IBlender +{ +public: + virtual LPCSTR getComment() { return "INTERNAL: accumulate reflected light"; } + virtual BOOL canBeDetailed() { return FALSE; } + virtual BOOL canBeLMAPped() { return FALSE; } + + virtual void Compile (CBlender_Compile& C); + + CBlender_accum_reflected(); + virtual ~CBlender_accum_reflected(); +}; diff --git a/src/Layers/xrRenderPC_GL/blender_light_spot.cpp b/src/Layers/xrRenderPC_GL/blender_light_spot.cpp new file mode 100644 index 00000000000..d5adec93f3c --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_light_spot.cpp @@ -0,0 +1,68 @@ +#include "stdafx.h" +#pragma hdrstop + +#include "Blender_light_spot.h" + +CBlender_accum_spot::CBlender_accum_spot () { description.CLS = 0; } +CBlender_accum_spot::~CBlender_accum_spot () { } + +void CBlender_accum_spot::Compile(CBlender_Compile& C) +{ + IBlender::Compile (C); + + BOOL b_HW_smap = RImplementation.o.HW_smap; + BOOL b_HW_PCF = RImplementation.o.HW_smap_PCF; + BOOL blend = RImplementation.o.fp16_blend; + D3DBLEND dest = blend?D3DBLEND_ONE:D3DBLEND_ZERO; + + switch (C.iElement) + { + case SE_L_FILL: // masking + C.r_Pass ("stub_notransform", "copy", false, FALSE, FALSE); + C.r_Sampler ("s_base", C.L_textures[0]); + C.r_End (); + break; + case SE_L_UNSHADOWED: // unshadowed + C.r_Pass ("accum_volume", "accum_spot_unshadowed", false, FALSE,FALSE,blend,D3DBLEND_ONE,dest); + C.r_Sampler_rtf ("s_position", r2_RT_P); + C.r_Sampler_rtf ("s_normal", r2_RT_N); + C.r_Sampler_clw ("s_material", r2_material); + C.r_Sampler ("s_lmap", C.L_textures[0],false,D3DTADDRESS_CLAMP); + C.r_Sampler_rtf ("s_accumulator", r2_RT_accum ); + C.r_End (); + break; + case SE_L_NORMAL: // normal + C.r_Pass ("accum_volume", "accum_spot_normal", false, FALSE,FALSE,blend,D3DBLEND_ONE,dest); + C.r_Sampler_rtf ("s_position", r2_RT_P); + C.r_Sampler_rtf ("s_normal", r2_RT_N); + C.r_Sampler_clw ("s_material", r2_material); + C.r_Sampler ("s_lmap", C.L_textures[0],false,D3DTADDRESS_CLAMP); + C.r_Sampler_cmp ("s_smap", r2_RT_smap_depth); + jitter (C); + C.r_Sampler_rtf ("s_accumulator", r2_RT_accum ); + C.r_End (); + break; + case SE_L_FULLSIZE: // normal-fullsize + C.r_Pass ("accum_volume", "accum_spot_fullsize", false, FALSE,FALSE,blend,D3DBLEND_ONE,dest); + C.r_Sampler_rtf ("s_position", r2_RT_P); + C.r_Sampler_rtf ("s_normal", r2_RT_N); + C.r_Sampler_clw ("s_material", r2_material); + C.r_Sampler ("s_lmap", C.L_textures[0],false,D3DTADDRESS_CLAMP); + C.r_Sampler_cmp ("s_smap", r2_RT_smap_depth); + jitter (C); + C.r_Sampler_rtf ("s_accumulator", r2_RT_accum ); + C.r_End (); + break; + case SE_L_TRANSLUENT: // shadowed + transluency + C.r_Pass ("accum_volume", "accum_spot_fullsize", false, FALSE,FALSE,blend,D3DBLEND_ONE,dest); + C.r_Sampler_rtf ("s_position", r2_RT_P); + C.r_Sampler_rtf ("s_normal", r2_RT_N); + C.r_Sampler_clw ("s_material", r2_material); + C.r_Sampler_clf ("s_lmap", r2_RT_smap_surf); // diff here + C.r_Sampler_cmp ("s_smap", r2_RT_smap_depth); + C.r_Sampler_rtf ("s_accumulator", r2_RT_accum ); + jitter (C); + C.r_End (); + break; + } +} diff --git a/src/Layers/xrRenderPC_GL/blender_light_spot.h b/src/Layers/xrRenderPC_GL/blender_light_spot.h new file mode 100644 index 00000000000..25967ed6b77 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_light_spot.h @@ -0,0 +1,14 @@ +#pragma once + +class CBlender_accum_spot : public IBlender +{ +public: + virtual LPCSTR getComment() { return "INTERNAL: accumulate spot light"; } + virtual BOOL canBeDetailed() { return FALSE; } + virtual BOOL canBeLMAPped() { return FALSE; } + + virtual void Compile (CBlender_Compile& C); + + CBlender_accum_spot(); + virtual ~CBlender_accum_spot(); +}; diff --git a/src/Layers/xrRenderPC_GL/blender_luminance.cpp b/src/Layers/xrRenderPC_GL/blender_luminance.cpp new file mode 100644 index 00000000000..e51f4ebceb2 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_luminance.cpp @@ -0,0 +1,32 @@ +#include "stdafx.h" +#pragma hdrstop + +#include "Blender_luminance.h" + +CBlender_luminance::CBlender_luminance () { description.CLS = 0; } +CBlender_luminance::~CBlender_luminance () { } + +void CBlender_luminance::Compile(CBlender_Compile& C) +{ + IBlender::Compile (C); + + switch (C.iElement) + { + case 0: // 256x256 => 64x64 + C.r_Pass ("stub_notransform_build", "bloom_luminance_1",false,FALSE,FALSE, FALSE); + C.r_Sampler_clf ("s_image", r2_RT_bloom1); + C.r_End (); + break; + case 1: // 64x64 => 8x8 + C.r_Pass ("stub_notransform_filter", "bloom_luminance_2",false,FALSE,FALSE, FALSE); + C.r_Sampler_clf ("s_image", r2_RT_luminance_t64); + C.r_End (); + break; + case 2: // 8x8 => 1x1, blending with old result + C.r_Pass ("stub_notransform_filter", "bloom_luminance_3",false,FALSE,FALSE, FALSE); + C.r_Sampler_clf ("s_image", r2_RT_luminance_t8 ); + C.r_Sampler_clf ("s_tonemap", r2_RT_luminance_src ); + C.r_End (); + break; + } +} diff --git a/src/Layers/xrRenderPC_GL/blender_luminance.h b/src/Layers/xrRenderPC_GL/blender_luminance.h new file mode 100644 index 00000000000..06933e09ad1 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_luminance.h @@ -0,0 +1,14 @@ +#pragma once + +class CBlender_luminance : public IBlender +{ +public: + virtual LPCSTR getComment() { return "INTERNAL: luminance estimate"; } + virtual BOOL canBeDetailed() { return FALSE; } + virtual BOOL canBeLMAPped() { return FALSE; } + + virtual void Compile (CBlender_Compile& C); + + CBlender_luminance(); + virtual ~CBlender_luminance(); +}; diff --git a/src/Layers/xrRenderPC_GL/blender_ssao.cpp b/src/Layers/xrRenderPC_GL/blender_ssao.cpp new file mode 100644 index 00000000000..74f29fa0b14 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_ssao.cpp @@ -0,0 +1,32 @@ +#include "stdafx.h" +#pragma hdrstop + +#include "Blender_SSAO.h" + +CBlender_SSAO::CBlender_SSAO () { description.CLS = 0; } +CBlender_SSAO::~CBlender_SSAO () { } + +void CBlender_SSAO::Compile (CBlender_Compile& C) +{ + IBlender::Compile (C); + + switch (C.iElement) + { + case 0: // calculate SSAO + C.r_Pass ("combine_1", "ssao_calc", FALSE, FALSE, FALSE); + C.r_Sampler_rtf ("s_position", r2_RT_P); + C.r_Sampler_rtf ("s_normal", r2_RT_N); + C.r_Sampler_rtf ("s_half_depth", r2_RT_half_depth); + jitter(C); + C.r_End (); + break; + case 1: // downsample HBAO source rendertarget + C.r_Pass ("combine_1", "depth_downs", FALSE, FALSE, FALSE); + C.r_Sampler_rtf ("s_position", r2_RT_P); + //C.r_Sampler_rtf ("s_normal", r2_RT_N); + //C.r_Sampler_rtf ("s_half_depth", r2_RT_half_depth); + //jitter(C); + C.r_End (); + break; + } +} diff --git a/src/Layers/xrRenderPC_GL/blender_ssao.h b/src/Layers/xrRenderPC_GL/blender_ssao.h new file mode 100644 index 00000000000..88140e81359 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/blender_ssao.h @@ -0,0 +1,14 @@ +#pragma once + +class CBlender_SSAO : public IBlender +{ +public: + virtual LPCSTR getComment() { return "INTERNAL: calc SSAO"; } + virtual BOOL canBeDetailed() { return FALSE; } + virtual BOOL canBeLMAPped() { return FALSE; } + + virtual void Compile (CBlender_Compile& C); + + CBlender_SSAO(); + virtual ~CBlender_SSAO(); +}; diff --git a/src/Layers/xrRenderPC_GL/glApplicationRender.cpp b/src/Layers/xrRenderPC_GL/glApplicationRender.cpp new file mode 100644 index 00000000000..78024ba4720 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glApplicationRender.cpp @@ -0,0 +1,270 @@ +#include "stdafx.h" +#include "glApplicationRender.h" +#include "../../xrEngine/x_ray.h" + +#include "../../xrEngine/GameFont.h" + +void glApplicationRender::Copy(IApplicationRender &_in) +{ + *this = *(glApplicationRender*)&_in; +} + +void glApplicationRender::LoadBegin() +{ + ll_hGeom.create(FVF::F_TL, RCache.Vertex.Buffer(), RCache.QuadIB); + sh_progress.create("hud\\default", "ui\\ui_load"); + hLevelLogo_Add.create("hud\\default", "ui\\ui_ingame2_back_add2_w.tga"); + + ll_hGeom2.create(FVF::F_TL, RCache.Vertex.Buffer(), NULL); +} + +void glApplicationRender::destroy_loading_shaders() +{ + hLevelLogo.destroy(); + sh_progress.destroy(); + hLevelLogo_Add.destroy(); +} + +void glApplicationRender::setLevelLogo(LPCSTR pszLogoName) +{ + hLevelLogo.create("hud\\default", pszLogoName); +} + +void glApplicationRender::KillHW() +{ + VERIFY(!"glApplicationRender::KillHW not implemented."); +} + +u32 calc_progress_color(u32, u32, int, int); + +void glApplicationRender::load_draw_internal(CApplication &owner) +{ + if (!sh_progress) + { + CHK_DX(HW.pDevice->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0, 0, 0, 0), 1, 0)); + return; + } + + float _w = (float)Device.dwWidth; + float _h = (float)Device.dwHeight; + bool b_ws = (_w / _h) > 1.34f; + bool b_16x9 = b_ws && ((_w / _h)>1.77f); + float ws_k = (b_16x9) ? 0.75f : 0.8333f; //16:9 or 16:10 + float ws_w = b_ws ? (b_16x9 ? 171.0f : 102.6f) : 0.0f; + + float bw = 1024.0f; + float bh = 768.0f; + Fvector2 k; + k.set(_w / bw, _h / bh); + + Fvector2 tsz; + tsz.set(1024, 1024); + Frect back_tex_coords; + Frect back_coords; + Fvector2 back_size; + Fvector2 back_tex_size; + + //background picture + static float offs = -0.5f; + + Fvector2 back_offset; + if (b_ws) + back_offset.set(ws_w*ws_k, 0.0f); //ws_w == 171 + else + back_offset.set(0.0f, 0.0f); + + + back_tex_size.set(1024, 768); + back_size.set(1024, 768); + if (b_ws) + back_size.x *= ws_k; //ws + + back_tex_coords.lt.set(0, 0); + back_tex_coords.rb.add(back_tex_coords.lt, back_tex_size); + + back_coords.lt.set(offs, offs); + back_coords.lt.add(back_offset); + back_coords.rb.add(back_coords.lt, back_size); + + back_coords.lt.mul(k); + back_coords.rb.mul(k); + draw_face(sh_progress, back_coords, back_tex_coords, tsz); + + if (b_ws) //draw additional frames (left&right) + { + //left + back_size.set(ws_w*ws_k, 768.0f); + + if (b_16x9) + { + back_tex_coords.lt.set(682, 0); + back_tex_coords.rb.set(850, 768); + } + else + { + back_tex_coords.lt.set(748, 0); + back_tex_coords.rb.set(850, 768); + } + back_coords.lt.set(offs, offs); + back_coords.rb.add(back_coords.lt, back_size); + back_coords.lt.mul(k); + back_coords.rb.mul(k); + + draw_face(hLevelLogo_Add, back_coords, back_tex_coords, tsz); + + //right + if (b_16x9) + { + back_tex_coords.lt.set(850, 0); + back_tex_coords.rb.set(1018, 768); + } + else + { + back_tex_coords.lt.set(850, 0); + back_tex_coords.rb.set(952, 768); + } + + back_coords.lt.set(1024.0f - back_size.x + offs, offs); + back_coords.rb.add(back_coords.lt, back_size); + back_coords.lt.mul(k); + back_coords.rb.mul(k); + + draw_face(hLevelLogo_Add, back_coords, back_tex_coords, tsz); + } + //progress bar + + back_tex_size.set(268, 37); + back_size.set(268, 37); + if (b_ws) + back_size.x *= ws_k; //ws + + back_tex_coords.lt.set(0, 768); + back_tex_coords.rb.add(back_tex_coords.lt, back_tex_size); + + back_coords.lt.set(379, 726); + if (b_ws) + back_coords.lt.x *= ws_k; + back_coords.lt.add(back_offset); + + back_coords.rb.add(back_coords.lt, back_size); + // + back_coords.lt.mul(k); + back_coords.rb.mul(k); + + back_tex_coords.lt.x /= tsz.x; + back_tex_coords.lt.y /= tsz.y; + back_tex_coords.rb.x /= tsz.x; + back_tex_coords.rb.y /= tsz.y; + + u32 Offset; + u32 C = 0xffffffff; + FVF::TL* pv = NULL; + u32 v_cnt = 40; + pv = (FVF::TL*)RCache.Vertex.Lock(2 * (v_cnt + 1), ll_hGeom2.stride(), Offset); + FVF::TL* _pv = pv; + float pos_delta = back_coords.width() / v_cnt; + float tc_delta = back_tex_coords.width() / v_cnt; + u32 clr = C; + + for (u32 idx = 0; idxset(back_coords.lt.x + pos_delta*idx + offs, back_coords.rb.y + offs, 0 + EPS_S, 1, clr, back_tex_coords.lt.x + tc_delta*idx, back_tex_coords.rb.y); pv++; + pv->set(back_coords.lt.x + pos_delta*idx + offs, back_coords.lt.y + offs, 0 + EPS_S, 1, clr, back_tex_coords.lt.x + tc_delta*idx, back_tex_coords.lt.y); pv++; + } + VERIFY(u32(pv - _pv) == 2 * (v_cnt + 1)); + RCache.Vertex.Unlock(2 * (v_cnt + 1), ll_hGeom2.stride()); + + RCache.set_Shader(sh_progress); + RCache.set_Geometry(ll_hGeom2); + RCache.Render(D3DPT_TRIANGLESTRIP, Offset, 2 * v_cnt); + + + // Draw title + VERIFY(owner.pFontSystem); + owner.pFontSystem->Clear(); + owner.pFontSystem->SetColor(color_rgba(157, 140, 120, 255)); + owner.pFontSystem->SetAligment(CGameFont::alCenter); + owner.pFontSystem->OutI(0.f, 0.815f, owner.app_title); + owner.pFontSystem->OnRender(); + + + //draw level-specific screenshot + if (hLevelLogo) + { + Frect r; + r.lt.set(257, 369); + + if (b_ws) + r.lt.x *= ws_k; + r.lt.add(back_offset); + + r.lt.x += offs; + r.lt.y += offs; + back_size.set(512, 256); + + if (b_ws) + back_size.x *= ws_k; //ws 0.625 + + r.rb.add(r.lt, back_size); + r.lt.mul(k); + r.rb.mul(k); + Frect logo_tex_coords; + logo_tex_coords.lt.set(0, 0); + logo_tex_coords.rb.set(1, 1); + + draw_face(hLevelLogo, r, logo_tex_coords, Fvector2().set(1, 1)); + } + + // TODO: DX10: remove this + { + //static int test = 0; + + // TODO: HACK: Test failure + //Msg("Compacting memory... Loading stage %d", test); + //Memory.mem_compact(); + + // if (test==29) + // { + // int b=0; + // } + + // VERIFY(test<3); + //++test; + } +} + +void glApplicationRender::draw_face(ref_shader& sh, Frect& coords, Frect& tex_coords, const Fvector2& tsz) +{ + u32 Offset; + u32 C = 0xffffffff; + FVF::TL* pv = NULL; + + tex_coords.lt.x /= tsz.x; + tex_coords.lt.y /= tsz.y; + tex_coords.rb.x /= tsz.x; + tex_coords.rb.y /= tsz.y; + + pv = (FVF::TL*) RCache.Vertex.Lock(4, ll_hGeom.stride(), Offset); + pv->set(coords.lt.x, coords.rb.y, C, tex_coords.lt.x, tex_coords.rb.y); pv++; + pv->set(coords.lt.x, coords.lt.y, C, tex_coords.lt.x, tex_coords.lt.y); pv++; + pv->set(coords.rb.x, coords.rb.y, C, tex_coords.rb.x, tex_coords.rb.y); pv++; + pv->set(coords.rb.x, coords.lt.y, C, tex_coords.rb.x, tex_coords.lt.y); pv++; + RCache.Vertex.Unlock(4, ll_hGeom.stride()); + + RCache.set_Shader(sh); + RCache.set_Geometry(ll_hGeom); + RCache.Render(D3DPT_TRIANGLELIST, Offset, 0, 4, 0, 2); +} + +u32 calc_progress_color(u32 idx, u32 total, int stage, int max_stage) +{ + if (idx>(total / 2)) + idx = total - idx; + + + float kk = (float(stage + 1) / float(max_stage))*(total / 2.0f); + float f = 1 / (exp((float(idx) - kk)*0.5f) + 1.0f); + + return color_argb_f(f, 1.0f, 1.0f, 1.0f); +} diff --git a/src/Layers/xrRenderPC_GL/glApplicationRender.h b/src/Layers/xrRenderPC_GL/glApplicationRender.h new file mode 100644 index 00000000000..7c33baa8f78 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glApplicationRender.h @@ -0,0 +1,26 @@ +#pragma once + +#include "..\..\Include\xrRender\ApplicationRender.h" + +class glApplicationRender : + public IApplicationRender +{ +public: + virtual void Copy(IApplicationRender &_in); + + virtual void LoadBegin(); + virtual void destroy_loading_shaders(); + virtual void setLevelLogo(LPCSTR pszLogoName); + virtual void load_draw_internal(CApplication &owner); + virtual void KillHW(); + +private: + ref_shader hLevelLogo; + ref_shader hLevelLogo_Add; + ref_geom ll_hGeom; + ref_geom ll_hGeom2; + + ref_shader sh_progress; + void draw_face(ref_shader& sh, Frect& coords, Frect& tex_coords, const Fvector2& tex_size); +}; + diff --git a/src/Layers/xrRenderPC_GL/glDebugRender.cpp b/src/Layers/xrRenderPC_GL/glDebugRender.cpp new file mode 100644 index 00000000000..fb114d37a34 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glDebugRender.cpp @@ -0,0 +1,17 @@ +#include "stdafx.h" + +#ifdef DEBUG + +#include "glDebugRender.h" + +glDebugRender DebugRenderImpl; + +glDebugRender::glDebugRender() +{ +} + +glDebugRender::~glDebugRender() +{ +} + +#endif // DEBUG diff --git a/src/Layers/xrRenderPC_GL/glDebugRender.h b/src/Layers/xrRenderPC_GL/glDebugRender.h new file mode 100644 index 00000000000..e2a81e97c96 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glDebugRender.h @@ -0,0 +1,36 @@ +#pragma once + +#ifdef DEBUG + +#include "../../Include/xrRender/DebugRender.h" + +class glDebugRender : + public IDebugRender +{ +public: + glDebugRender(); + ~glDebugRender(); + + virtual void Render() { }; + virtual void add_lines(Fvector const *vertices, u32 const &vertex_count, u16 const *pairs, u32 const &pair_count, u32 const &color) { }; + + // routed to RCache + virtual void NextSceneMode() { }; + virtual void ZEnable(bool bEnable) { }; + virtual void OnFrameEnd() { }; + virtual void SetShader(const debug_shader &shader) { }; + virtual void CacheSetXformWorld(const Fmatrix& M) { }; + virtual void CacheSetCullMode(CullMode) { }; + virtual void SetAmbient(u32 colour) { }; + + // Shaders + virtual void SetDebugShader(dbgShaderHandle shdHandle) { }; + virtual void DestroyDebugShader(dbgShaderHandle shdHandle) { }; + +#ifdef DEBUG + virtual void dbg_DrawTRI(Fmatrix& T, Fvector& p1, Fvector& p2, Fvector& p3, u32 C) { }; +#endif // DEBUG +}; + +extern glDebugRender DebugRenderImpl; +#endif // DEBUG diff --git a/src/Layers/xrRenderPC_GL/glEnvironmentRender.cpp b/src/Layers/xrRenderPC_GL/glEnvironmentRender.cpp new file mode 100644 index 00000000000..dad071e1ac1 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glEnvironmentRender.cpp @@ -0,0 +1,311 @@ +#include "stdafx.h" +#include "glEnvironmentRender.h" + +#include "glRenderDeviceRender.h" + +#include "../../xrEngine/environment.h" +#include "../../Layers/xrRender/ResourceManager.h" + +#include "../../xrEngine/xr_efflensflare.h" + + +////////////////////////////////////////////////////////////////////////// +// half box def +static Fvector3 hbox_verts[24] = +{ + { -1.f, -1.f, -1.f }, { -1.f, -1.01f, -1.f }, // down + { 1.f, -1.f, -1.f }, { 1.f, -1.01f, -1.f }, // down + { -1.f, -1.f, 1.f }, { -1.f, -1.01f, 1.f }, // down + { 1.f, -1.f, 1.f }, { 1.f, -1.01f, 1.f }, // down + { -1.f, 1.f, -1.f }, { -1.f, 1.f, -1.f }, + { 1.f, 1.f, -1.f }, { 1.f, 1.f, -1.f }, + { -1.f, 1.f, 1.f }, { -1.f, 1.f, 1.f }, + { 1.f, 1.f, 1.f }, { 1.f, 1.f, 1.f }, + { -1.f, 0.f, -1.f }, { -1.f, -1.f, -1.f }, // half + { 1.f, 0.f, -1.f }, { 1.f, -1.f, -1.f }, // half + { 1.f, 0.f, 1.f }, { 1.f, -1.f, 1.f }, // half + { -1.f, 0.f, 1.f }, { -1.f, -1.f, 1.f } // half +}; +static u16 hbox_faces[20 * 3] = +{ + 0, 2, 3, + 3, 1, 0, + 4, 5, 7, + 7, 6, 4, + 0, 1, 9, + 9, 8, 0, + 8, 9, 5, + 5, 4, 8, + 1, 3, 10, + 10, 9, 1, + 9, 10, 7, + 7, 5, 9, + 3, 2, 11, + 11, 10, 3, + 10, 11, 6, + 6, 7, 10, + 2, 0, 8, + 8, 11, 2, + 11, 8, 4, + 4, 6, 11 +}; + +#pragma pack(push,1) +struct v_skybox { + Fvector3 p; + u32 color; + Fvector3 uv[2]; + + void set(Fvector3& _p, u32 _c, Fvector3& _tc) + { + p = _p; + color = _c; + uv[0] = _tc; + uv[1] = _tc; + } +}; +const u32 v_skybox_fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEXCOORDSIZE3(1); +struct v_clouds { + Fvector3 p; + u32 color; + u32 intensity; + void set(Fvector3& _p, u32 _c, u32 _i) + { + p = _p; + color = _c; + intensity = _i; + } +}; +const u32 v_clouds_fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR; +#pragma pack(pop) + +void glEnvDescriptorRender::Copy(IEnvDescriptorRender &_in) +{ + *this = *(glEnvDescriptorRender*)&_in; +} + +void glEnvDescriptorMixerRender::Copy(IEnvDescriptorMixerRender &_in) +{ + *this = *(glEnvDescriptorMixerRender*)&_in; +} + +void glEnvironmentRender::Copy(IEnvironmentRender &_in) +{ + *this = *(glEnvironmentRender*)&_in; +} + +particles_systems::library_interface const& glEnvironmentRender::particles_systems_library() +{ + return (RImplementation.PSLibrary); +} + +void glEnvDescriptorMixerRender::Destroy() +{ + sky_r_textures.clear(); + sky_r_textures_env.clear(); + clouds_r_textures.clear(); +} + +void glEnvDescriptorMixerRender::Clear() +{ + std::pair zero = mk_pair(u32(0), ref_texture(0)); + sky_r_textures.clear(); + sky_r_textures.push_back(zero); + sky_r_textures.push_back(zero); + sky_r_textures.push_back(zero); + + sky_r_textures_env.clear(); + sky_r_textures_env.push_back(zero); + sky_r_textures_env.push_back(zero); + sky_r_textures_env.push_back(zero); + + clouds_r_textures.clear(); + clouds_r_textures.push_back(zero); + clouds_r_textures.push_back(zero); + clouds_r_textures.push_back(zero); +} + +void glEnvDescriptorMixerRender::lerp(IEnvDescriptorRender *inA, IEnvDescriptorRender *inB) +{ + glEnvDescriptorRender *pA = (glEnvDescriptorRender *)inA; + glEnvDescriptorRender *pB = (glEnvDescriptorRender *)inB; + + sky_r_textures.clear(); + sky_r_textures.push_back(mk_pair(0, pA->sky_texture)); + sky_r_textures.push_back(mk_pair(1, pB->sky_texture)); + + sky_r_textures_env.clear(); + + sky_r_textures_env.push_back(mk_pair(0, pA->sky_texture_env)); + sky_r_textures_env.push_back(mk_pair(1, pB->sky_texture_env)); + + clouds_r_textures.clear(); + clouds_r_textures.push_back(mk_pair(0, pA->clouds_texture)); + clouds_r_textures.push_back(mk_pair(1, pB->clouds_texture)); +} + +void glEnvDescriptorRender::OnDeviceCreate(CEnvDescriptor &owner) +{ + if (owner.sky_texture_name.size()) + sky_texture.create(owner.sky_texture_name.c_str()); + + if (owner.sky_texture_env_name.size()) + sky_texture_env.create(owner.sky_texture_env_name.c_str()); + + if (owner.clouds_texture_name.size()) + clouds_texture.create(owner.clouds_texture_name.c_str()); +} + +void glEnvDescriptorRender::OnDeviceDestroy() +{ + sky_texture.destroy(); + sky_texture_env.destroy(); + clouds_texture.destroy(); +} + +glEnvironmentRender::glEnvironmentRender() +{ + tsky0 = DEV->_CreateTexture("$user$sky0"); + tsky1 = DEV->_CreateTexture("$user$sky1"); +} + +void glEnvironmentRender::OnFrame(CEnvironment &env) +{ + glEnvDescriptorMixerRender &mixRen = *(glEnvDescriptorMixerRender*)&*env.CurrentEnv->m_pDescriptorMixer; + + if (::Render->get_generation() == IRender_interface::GENERATION_R2){ + // TODO: OGL: Implement tone mapping. + } + + //. Setup skybox textures, somewhat ugly + GLuint e0 = mixRen.sky_r_textures[0].second->surface_get(); + GLuint e1 = mixRen.sky_r_textures[1].second->surface_get(); + + tsky0->surface_set(GL_TEXTURE_CUBE_MAP, e0); + tsky1->surface_set(GL_TEXTURE_CUBE_MAP, e1); + + // ******************** Environment params (setting) + // TODO: OGL: Implement environment parameters setting for OGL (if necessary) +} + +void glEnvironmentRender::OnLoad() +{ + tonemap = DEV->_CreateTexture("$user$tonemap"); //. hack +} + +void glEnvironmentRender::OnUnload() +{ + tonemap = 0; +} + +void glEnvironmentRender::RenderSky(CEnvironment &env) +{ + // clouds_sh.create ("clouds","null"); + //. this is the bug-fix for the case when the sky is broken + //. for some unknown reason the geoms happen to be invalid sometimes + //. if vTune show this in profile, please add simple cache (move-to-forward last found) + //. to the following functions: + //. CResourceManager::_CreateDecl + //. CResourceManager::CreateGeom + if (env.bNeed_re_create_env) + { + sh_2sky.create(&m_b_skybox, "skybox_2t"); + sh_2geom.create(v_skybox_fvf, RCache.Vertex.Buffer(), RCache.Index.Buffer()); + clouds_sh.create("clouds", "null"); + clouds_geom.create(v_clouds_fvf, RCache.Vertex.Buffer(), RCache.Index.Buffer()); + env.bNeed_re_create_env = FALSE; + } + ::Render->rmFar(); + + glEnvDescriptorMixerRender &mixRen = *(glEnvDescriptorMixerRender*)&*env.CurrentEnv->m_pDescriptorMixer; + + // draw sky box + Fmatrix mSky; + mSky.rotateY(env.CurrentEnv->sky_rotation); + mSky.translate_over(Device.vCameraPosition); + + u32 i_offset, v_offset; + u32 C = color_rgba(iFloor(env.CurrentEnv->sky_color.x*255.f), iFloor(env.CurrentEnv->sky_color.y*255.f), iFloor(env.CurrentEnv->sky_color.z*255.f), iFloor(env.CurrentEnv->weight*255.f)); + + // Fill index buffer + u16* pib = RCache.Index.Lock(20 * 3, i_offset); + CopyMemory(pib, hbox_faces, 20 * 3 * 2); + RCache.Index.Unlock(20 * 3); + + // Fill vertex buffer + v_skybox* pv = (v_skybox*)RCache.Vertex.Lock(12, sh_2geom.stride(), v_offset); + for (u32 v = 0; v<12; v++) pv[v].set(hbox_verts[v * 2], C, hbox_verts[v * 2 + 1]); + RCache.Vertex.Unlock(12, sh_2geom.stride()); + + // Render + RCache.set_xform_world(mSky); + RCache.set_Geometry(sh_2geom); + RCache.set_Shader(sh_2sky); + // RCache.set_Textures (&env.CurrentEnv->sky_r_textures); + RCache.set_Textures(&mixRen.sky_r_textures); + RCache.Render(D3DPT_TRIANGLELIST, v_offset, 0, 12, i_offset, 20); + + // Sun + ::Render->rmNormal(); + env.eff_LensFlare->Render(TRUE, FALSE, FALSE); +} + +void glEnvironmentRender::RenderClouds(CEnvironment &env) +{ + ::Render->rmFar(); + + Fmatrix mXFORM, mScale; + mScale.scale(10, 0.4f, 10); + mXFORM.rotateY(env.CurrentEnv->sky_rotation); + mXFORM.mulB_43(mScale); + mXFORM.translate_over(Device.vCameraPosition); + + Fvector wd0, wd1; + Fvector4 wind_dir; + wd0.setHP(PI_DIV_4, 0); + wd1.setHP(PI_DIV_4 + PI_DIV_8, 0); + wind_dir.set(wd0.x, wd0.z, wd1.x, wd1.z).mul(0.5f).add(0.5f).mul(255.f); + u32 i_offset, v_offset; + u32 C0 = color_rgba(iFloor(wind_dir.x), iFloor(wind_dir.y), iFloor(wind_dir.w), iFloor(wind_dir.z)); + u32 C1 = color_rgba(iFloor(env.CurrentEnv->clouds_color.x*255.f), iFloor(env.CurrentEnv->clouds_color.y*255.f), iFloor(env.CurrentEnv->clouds_color.z*255.f), iFloor(env.CurrentEnv->clouds_color.w*255.f)); + + // Fill index buffer + u16* pib = RCache.Index.Lock(env.CloudsIndices.size(), i_offset); + CopyMemory(pib, &env.CloudsIndices.front(), env.CloudsIndices.size()*sizeof(u16)); + RCache.Index.Unlock(env.CloudsIndices.size()); + + // Fill vertex buffer + v_clouds* pv = (v_clouds*)RCache.Vertex.Lock(env.CloudsVerts.size(), clouds_geom.stride(), v_offset); + for (FvectorIt it = env.CloudsVerts.begin(); it != env.CloudsVerts.end(); it++, pv++) + pv->set(*it, C0, C1); + RCache.Vertex.Unlock(env.CloudsVerts.size(), clouds_geom.stride()); + + // Render + RCache.set_xform_world(mXFORM); + RCache.set_Geometry(clouds_geom); + RCache.set_Shader(clouds_sh); + glEnvDescriptorMixerRender &mixRen = *(glEnvDescriptorMixerRender*)&*env.CurrentEnv->m_pDescriptorMixer; + RCache.set_Textures(&mixRen.clouds_r_textures); + RCache.Render(D3DPT_TRIANGLELIST, v_offset, 0, env.CloudsVerts.size(), i_offset, env.CloudsIndices.size() / 3); + + ::Render->rmNormal(); +} + +void glEnvironmentRender::OnDeviceCreate() +{ + sh_2sky.create(&m_b_skybox, "skybox_2t"); + sh_2geom.create(v_skybox_fvf, RCache.Vertex.Buffer(), RCache.Index.Buffer()); + clouds_sh.create("clouds", "null"); + clouds_geom.create(v_clouds_fvf, RCache.Vertex.Buffer(), RCache.Index.Buffer()); +} + +void glEnvironmentRender::OnDeviceDestroy() +{ + tsky0->surface_set(GL_TEXTURE_CUBE_MAP, NULL); + tsky1->surface_set(GL_TEXTURE_CUBE_MAP, NULL); + + sh_2sky.destroy(); + sh_2geom.destroy(); + clouds_sh.destroy(); + clouds_geom.destroy(); +} diff --git a/src/Layers/xrRenderPC_GL/glEnvironmentRender.h b/src/Layers/xrRenderPC_GL/glEnvironmentRender.h new file mode 100644 index 00000000000..b1dcc72dc01 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glEnvironmentRender.h @@ -0,0 +1,82 @@ +#pragma once + +#include "..\..\include\xrRender\EnvironmentRender.h" + +#include "..\xrRender\blenders\blender.h" +class CBlender_skybox : + public IBlender +{ +public: + virtual LPCSTR getComment() { return "INTERNAL: combiner"; } + virtual BOOL canBeDetailed() { return FALSE; } + virtual BOOL canBeLMAPped() { return FALSE; } + + virtual void Compile(CBlender_Compile& C) + { + C.r_Pass("sky2", "sky2", FALSE, TRUE, FALSE); + C.r_Sampler_clf("s_sky0", "$null"); + C.r_Sampler_clf("s_sky1", "$null"); + C.r_Sampler_rtf("s_tonemap", "$user$tonemap"); //. hack + C.PassSET_ZB(FALSE, FALSE); + C.r_End(); + } +}; + +class glEnvDescriptorRender : public IEnvDescriptorRender +{ + friend class glEnvDescriptorMixerRender; +public: + virtual void OnDeviceCreate(CEnvDescriptor &owner); + virtual void OnDeviceDestroy(); + + virtual void Copy(IEnvDescriptorRender &_in); +private: + ref_texture sky_texture; + ref_texture sky_texture_env; + ref_texture clouds_texture; +}; + +class glEnvDescriptorMixerRender : public IEnvDescriptorMixerRender +{ +public: + virtual void Copy(IEnvDescriptorMixerRender &_in); + + virtual void Destroy(); + virtual void Clear(); + virtual void lerp(IEnvDescriptorRender *inA, IEnvDescriptorRender *inB); + //private: +public: + STextureList sky_r_textures; + STextureList sky_r_textures_env; + STextureList clouds_r_textures; +}; + +class glEnvironmentRender : + public IEnvironmentRender +{ +public: + glEnvironmentRender(); + + virtual void Copy(IEnvironmentRender &_in); + + virtual void OnFrame(CEnvironment &env); + virtual void OnLoad(); + virtual void OnUnload(); + virtual void RenderSky(CEnvironment &env); + virtual void RenderClouds(CEnvironment &env); + virtual void OnDeviceCreate(); + virtual void OnDeviceDestroy(); + virtual particles_systems::library_interface const& particles_systems_library(); + +private: + CBlender_skybox m_b_skybox; + + ref_shader sh_2sky; + ref_geom sh_2geom; + + ref_shader clouds_sh; + ref_geom clouds_geom; + + ref_texture tonemap; + ref_texture tsky0, tsky1; +}; diff --git a/src/Layers/xrRenderPC_GL/glFontRender.cpp b/src/Layers/xrRenderPC_GL/glFontRender.cpp new file mode 100644 index 00000000000..d2163d63916 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glFontRender.cpp @@ -0,0 +1,149 @@ +#include "stdafx.h" +#include "glFontRender.h" + +#include "../../xrEngine/GameFont.h" + +glFontRender::glFontRender() +{ + +} + +glFontRender::~glFontRender() +{ + pShader.destroy(); + pGeom.destroy(); +} + +void glFontRender::Initialize(LPCSTR cShader, LPCSTR cTexture) +{ + pShader.create(cShader, cTexture); + pGeom.create(FVF::F_TL, RCache.Vertex.Buffer(), RCache.QuadIB); +} +extern ENGINE_API BOOL g_bRendering; +extern ENGINE_API Fvector2 g_current_font_scale; +void glFontRender::OnRender(CGameFont &owner) +{ + VERIFY(g_bRendering); + if (pShader) RCache.set_Shader(pShader); + + if (!(owner.uFlags&CGameFont::fsValid)){ + CTexture* T = RCache.get_ActiveTexture(0); + owner.vTS.set((int)T->get_Width(), (int)T->get_Height()); + owner.fTCHeight = owner.fHeight / float(owner.vTS.y); + owner.uFlags |= CGameFont::fsValid; + } + + for (u32 i = 0; iset(X, Y2, clr2, tu, tv + owner.fTCHeight); v++; + v->set(X, Y, clr, tu, tv); v++; + v->set(X + scw, Y2, clr2, tu + fTCWidth, tv + owner.fTCHeight); v++; + v->set(X + scw, Y, clr, tu + fTCWidth, tv); v++; + } + X += scw * owner.vInterval.x; + if (owner.IsMultibyte()) { + X -= 2; + if (IsNeedSpaceCharacter(wsStr[1 + j])) + X += owner.fXStep; + } + } + } + } + + // Unlock and draw + u32 vCount = (u32)(v - start); + RCache.Vertex.Unlock(vCount, pGeom.stride()); + if (vCount){ + RCache.set_Geometry(pGeom); + RCache.Render(D3DPT_TRIANGLELIST, vOffset, 0, vCount, 0, vCount / 2); + } + } +} diff --git a/src/Layers/xrRenderPC_GL/glFontRender.h b/src/Layers/xrRenderPC_GL/glFontRender.h new file mode 100644 index 00000000000..a15762abd8b --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glFontRender.h @@ -0,0 +1,18 @@ +#pragma once + +#include "..\..\Include\xrRender\FontRender.h" + +class glFontRender : + public IFontRender +{ +public: + glFontRender(); + virtual ~glFontRender(); + + virtual void Initialize(LPCSTR cShader, LPCSTR cTexture); + virtual void OnRender(CGameFont &owner); + +private: + ref_shader pShader; + ref_geom pGeom; +}; diff --git a/src/Layers/xrRenderPC_GL/glLensFlareRender.cpp b/src/Layers/xrRenderPC_GL/glLensFlareRender.cpp new file mode 100644 index 00000000000..b3cc0b31f6d --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glLensFlareRender.cpp @@ -0,0 +1,125 @@ +#include "stdafx.h" +#include "glLensFlareRender.h" +#include "../../xrEngine/xr_efflensflare.h" +#include "../../xrEngine/iGame_persistent.h" +#define MAX_Flares 24 + +#define FAR_DIST g_pGamePersistent->Environment().CurrentEnv->far_plane + +void glFlareRender::Copy(IFlareRender &_in) +{ + *this = *(glFlareRender*)&_in; +} + +void glFlareRender::CreateShader(LPCSTR sh_name, LPCSTR tex_name) +{ + if (tex_name&&tex_name[0]) + hShader.create(sh_name, tex_name); +} + +void glFlareRender::DestroyShader() +{ + hShader.destroy(); +} + +void glLensFlareRender::Copy(ILensFlareRender &_in) +{ + *this = *(glLensFlareRender*)&_in; +} + +void glLensFlareRender::Render(CLensFlare &owner, BOOL bSun, BOOL bFlares, BOOL bGradient) +{ + Fcolor dwLight; + Fcolor color; + Fvector vec, vecSx, vecSy; + Fvector vecDx, vecDy; + + dwLight.set(owner.LightColor); + svector _2render; + + u32 VS_Offset; + FVF::LIT *pv = (FVF::LIT*) RCache.Vertex.Lock(MAX_Flares * 4, hGeom.stride(), VS_Offset); + + float fDistance = FAR_DIST*0.75f; + + if (bSun){ + if (owner.m_Current->m_Flags.is(CLensFlareDescriptor::flSource)){ + vecSx.mul(owner.vecX, owner.m_Current->m_Source.fRadius*fDistance); + vecSy.mul(owner.vecY, owner.m_Current->m_Source.fRadius*fDistance); + if (owner.m_Current->m_Source.ignore_color) color.set(1.f, 1.f, 1.f, 1.f); + else color.set(dwLight); + color.a *= owner.m_StateBlend; + u32 c = color.get(); + pv->set(owner.vecLight.x + vecSx.x - vecSy.x, owner.vecLight.y + vecSx.y - vecSy.y, owner.vecLight.z + vecSx.z - vecSy.z, c, 0, 0); pv++; + pv->set(owner.vecLight.x + vecSx.x + vecSy.x, owner.vecLight.y + vecSx.y + vecSy.y, owner.vecLight.z + vecSx.z + vecSy.z, c, 0, 1); pv++; + pv->set(owner.vecLight.x - vecSx.x - vecSy.x, owner.vecLight.y - vecSx.y - vecSy.y, owner.vecLight.z - vecSx.z - vecSy.z, c, 1, 0); pv++; + pv->set(owner.vecLight.x - vecSx.x + vecSy.x, owner.vecLight.y - vecSx.y + vecSy.y, owner.vecLight.z - vecSx.z + vecSy.z, c, 1, 1); pv++; + _2render.push_back(((glFlareRender*)&*owner.m_Current->m_Source.m_pRender)->hShader); + } + } + if (owner.fBlend >= EPS_L) + { + if (bFlares){ + vecDx.normalize(owner.vecAxis); + vecDy.crossproduct(vecDx, owner.vecDir); + if (owner.m_Current->m_Flags.is(CLensFlareDescriptor::flFlare)){ + for (CLensFlareDescriptor::FlareIt it = owner.m_Current->m_Flares.begin(); it != owner.m_Current->m_Flares.end(); it++){ + CLensFlareDescriptor::SFlare& F = *it; + vec.mul(owner.vecAxis, F.fPosition); + vec.add(owner.vecCenter); + vecSx.mul(vecDx, F.fRadius*fDistance); + vecSy.mul(vecDy, F.fRadius*fDistance); + float cl = F.fOpacity * owner.fBlend * owner.m_StateBlend; + color.set(dwLight); + color.mul_rgba(cl); + u32 c = color.get(); + pv->set(vec.x + vecSx.x - vecSy.x, vec.y + vecSx.y - vecSy.y, vec.z + vecSx.z - vecSy.z, c, 0, 0); pv++; + pv->set(vec.x + vecSx.x + vecSy.x, vec.y + vecSx.y + vecSy.y, vec.z + vecSx.z + vecSy.z, c, 0, 1); pv++; + pv->set(vec.x - vecSx.x - vecSy.x, vec.y - vecSx.y - vecSy.y, vec.z - vecSx.z - vecSy.z, c, 1, 0); pv++; + pv->set(vec.x - vecSx.x + vecSy.x, vec.y - vecSx.y + vecSy.y, vec.z - vecSx.z + vecSy.z, c, 1, 1); pv++; + _2render.push_back(((glFlareRender*)&*it->m_pRender)->hShader); + } + } + } + // gradient + if (bGradient && (owner.fGradientValue >= EPS_L)){ + if (owner.m_Current->m_Flags.is(CLensFlareDescriptor::flGradient)){ + vecSx.mul(owner.vecX, owner.m_Current->m_Gradient.fRadius*owner.fGradientValue*fDistance); + vecSy.mul(owner.vecY, owner.m_Current->m_Gradient.fRadius*owner.fGradientValue*fDistance); + + color.set(dwLight); + color.mul_rgba(owner.fGradientValue*owner.m_StateBlend); + + u32 c = color.get(); + pv->set(owner.vecLight.x + vecSx.x - vecSy.x, owner.vecLight.y + vecSx.y - vecSy.y, owner.vecLight.z + vecSx.z - vecSy.z, c, 0, 0); pv++; + pv->set(owner.vecLight.x + vecSx.x + vecSy.x, owner.vecLight.y + vecSx.y + vecSy.y, owner.vecLight.z + vecSx.z + vecSy.z, c, 0, 1); pv++; + pv->set(owner.vecLight.x - vecSx.x - vecSy.x, owner.vecLight.y - vecSx.y - vecSy.y, owner.vecLight.z - vecSx.z - vecSy.z, c, 1, 0); pv++; + pv->set(owner.vecLight.x - vecSx.x + vecSy.x, owner.vecLight.y - vecSx.y + vecSy.y, owner.vecLight.z - vecSx.z + vecSy.z, c, 1, 1); pv++; + _2render.push_back(((glFlareRender*)&*owner.m_Current->m_Gradient.m_pRender)->hShader); + } + } + } + RCache.Vertex.Unlock(_2render.size() * 4, hGeom.stride()); + + RCache.set_xform_world(Fidentity); + RCache.set_Geometry(hGeom); + for (u32 i = 0; i<_2render.size(); i++) + { + if (_2render[i]) + { + u32 vBase = i * 4 + VS_Offset; + RCache.set_Shader(_2render[i]); + RCache.Render(D3DPT_TRIANGLELIST, vBase, 0, 4, 0, 2); + } + } +} + +void glLensFlareRender::OnDeviceCreate() +{ + hGeom.create(FVF::F_LIT, RCache.Vertex.Buffer(), RCache.QuadIB); +} + +void glLensFlareRender::OnDeviceDestroy() +{ + hGeom.destroy(); +} diff --git a/src/Layers/xrRenderPC_GL/glLensFlareRender.h b/src/Layers/xrRenderPC_GL/glLensFlareRender.h new file mode 100644 index 00000000000..d04d5fa7cfc --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glLensFlareRender.h @@ -0,0 +1,31 @@ +#pragma once + +#include "..\..\Include\xrRender\LensFlareRender.h" + +class glFlareRender : + public IFlareRender +{ +public: + virtual void Copy(IFlareRender &_in); + + virtual void CreateShader(LPCSTR sh_name, LPCSTR tex_name); + virtual void DestroyShader(); + + //private: +public: + ref_shader hShader; +}; + +class glLensFlareRender : + public ILensFlareRender +{ +public: + virtual void Copy(ILensFlareRender &_in); + + virtual void Render(CLensFlare &owner, BOOL bSun, BOOL bFlares, BOOL bGradient); + + virtual void OnDeviceCreate(); + virtual void OnDeviceDestroy(); +private: + ref_geom hGeom; +}; diff --git a/src/Layers/xrRenderPC_GL/glObjectSpaceRender.cpp b/src/Layers/xrRenderPC_GL/glObjectSpaceRender.cpp new file mode 100644 index 00000000000..145cacfa3f1 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glObjectSpaceRender.cpp @@ -0,0 +1,61 @@ +#include "stdafx.h" + +#ifdef DEBUG + +#include "glObjectSpaceRender.h" + +glObjectSpaceRender::glObjectSpaceRender() +{ + m_shDebug.create("debug\\wireframe", "$null"); +} + +glObjectSpaceRender::~glObjectSpaceRender() +{ + m_shDebug.destroy(); +} + +void glObjectSpaceRender::Copy(IObjectSpaceRender &_in) +{ + *this = *(glObjectSpaceRender*)&_in; +} + +void glObjectSpaceRender::dbgAddSphere(const Fsphere &sphere, u32 colour) +{ + dbg_S.push_back(mk_pair(sphere, colour)); +} + +void glObjectSpaceRender::dbgRender() +{ + R_ASSERT(bDebug); + + RCache.set_Shader(m_shDebug); + for (u32 i = 0; i& P = dbg_S[i]; + Fsphere& S = P.first; + Fmatrix M; + M.scale(S.R, S.R, S.R); + M.translate_over(S.P); + RCache.dbg_DrawEllipse(M, P.second); + } + dbg_S.clear(); +} + +void glObjectSpaceRender::SetShader() +{ + RCache.set_Shader(m_shDebug); +} + +#endif // DEBUG diff --git a/src/Layers/xrRenderPC_GL/glObjectSpaceRender.h b/src/Layers/xrRenderPC_GL/glObjectSpaceRender.h new file mode 100644 index 00000000000..b853e37722d --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glObjectSpaceRender.h @@ -0,0 +1,24 @@ +#pragma once + +#ifdef DEBUG + +#include "..\..\Include\xrRender\ObjectSpaceRender.h" + +class glObjectSpaceRender : public IObjectSpaceRender +{ +public: + glObjectSpaceRender(); + virtual ~glObjectSpaceRender(); + virtual void Copy(IObjectSpaceRender &_in); + + virtual void dbgRender(); + virtual void dbgAddSphere(const Fsphere &sphere, u32 colour); + virtual void SetShader(); + +private: + ref_shader m_shDebug; + clQueryCollision q_debug; // MT: dangerous + xr_vector > dbg_S; // MT: dangerous +}; + +#endif // DEBUG diff --git a/src/Layers/xrRenderPC_GL/glRainRender.cpp b/src/Layers/xrRenderPC_GL/glRainRender.cpp new file mode 100644 index 00000000000..4ba4da45d16 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glRainRender.cpp @@ -0,0 +1,261 @@ +#include "stdafx.h" +#include "glRainRender.h" + +#include "../../xrEngine/Rain.h" + +// Warning: duplicated in rain.cpp +static const int max_desired_items = 2500; +static const float source_radius = 12.5f; +static const float source_offset = 40.f; +static const float max_distance = source_offset*1.25f; +static const float sink_offset = -(max_distance - source_offset); +static const float drop_length = 5.f; +static const float drop_width = 0.30f; +static const float drop_angle = 3.0f; +static const float drop_max_angle = deg2rad(10.f); +static const float drop_max_wind_vel = 20.0f; +static const float drop_speed_min = 40.f; +static const float drop_speed_max = 80.f; + +const int max_particles = 1000; +const int particles_cache = 400; +const float particles_time = .3f; + +glRainRender::glRainRender() +{ + IReader* F = FS.r_open("$game_meshes$", "dm\\rain.dm"); + VERIFY3(F, "Can't open file.", "dm\\rain.dm"); + + DM_Drop = ::RImplementation.model_CreateDM(F); + + // + SH_Rain.create("effects\\rain", "fx\\fx_rain"); + hGeom_Rain.create(FVF::F_LIT, RCache.Vertex.Buffer(), RCache.QuadIB); + hGeom_Drops.create(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, RCache.Vertex.Buffer(), RCache.Index.Buffer()); + + FS.r_close(F); +} + +glRainRender::~glRainRender() +{ + ::RImplementation.model_Delete(DM_Drop); +} + +void glRainRender::Copy(IRainRender &_in) +{ + *this = *(glRainRender*)&_in; +} + +#include "../../xrEngine/iGame_persistent.h" + +void glRainRender::Render(CEffect_Rain &owner) +{ + float factor = g_pGamePersistent->Environment().CurrentEnv->rain_density; + if (factorEnvironment().CurrentEnv->rain_color; + u32 u_rain_color = color_rgba_f(f_rain_color.x, f_rain_color.y, f_rain_color.z, factor_visual); + + // born _new_ if needed + float b_radius_wrap_sqr = _sqr((source_radius + .5f)); + if (owner.items.size()vb_stride, vOffset); + FVF::LIT *start = verts; + const Fvector& vEye = Device.vCameraPosition; + for (u32 I = 0; ITEST1.Begin(); + Fvector wdir; wdir.set(one.P.x - vEye.x, 0, one.P.z - vEye.z); + float wlen = wdir.square_magnitude(); + if (wlen>b_radius_wrap_sqr) { + wlen = _sqrt(wlen); + //. Device.Statistic->TEST3.Begin(); + if ((one.P.y - vEye.y)TEST3.End(); + } + Device.Statistic->TEST1.End(); + + // Build line + Fvector& pos_head = one.P; + Fvector pos_trail; pos_trail.mad(pos_head, one.D, -drop_length*factor_visual); + + // Culling + Fvector sC, lineD; float sR; + sC.sub(pos_head, pos_trail); + lineD.normalize(sC); + sC.mul(.5f); + sR = sC.magnitude(); + sC.add(pos_trail); + if (!::Render->ViewBase.testSphere_dirty(sC, sR)) continue; + + static Fvector2 UV[2][4] = { + { { 0, 1 }, { 0, 0 }, { 1, 1 }, { 1, 0 } }, + { { 1, 0 }, { 1, 1 }, { 0, 0 }, { 0, 1 } } + }; + + // Everything OK - build vertices + Fvector P, lineTop, camDir; + camDir.sub(sC, vEye); + camDir.normalize(); + lineTop.crossproduct(camDir, lineD); + float w = drop_width; + u32 s = one.uv_set; + P.mad(pos_trail, lineTop, -w); verts->set(P, u_rain_color, UV[s][0].x, UV[s][0].y); verts++; + P.mad(pos_trail, lineTop, w); verts->set(P, u_rain_color, UV[s][1].x, UV[s][1].y); verts++; + P.mad(pos_head, lineTop, -w); verts->set(P, u_rain_color, UV[s][2].x, UV[s][2].y); verts++; + P.mad(pos_head, lineTop, w); verts->set(P, u_rain_color, UV[s][3].x, UV[s][3].y); verts++; + } + u32 vCount = (u32)(verts - start); + RCache.Vertex.Unlock(vCount, hGeom_Rain->vb_stride); + + // Render if needed + if (vCount) { + //HW.pDevice->SetRenderState (D3DRS_CULLMODE,D3DCULL_NONE); + RCache.set_CullMode(CULL_NONE); + RCache.set_xform_world(Fidentity); + RCache.set_Shader(SH_Rain); + RCache.set_Geometry(hGeom_Rain); + RCache.Render(D3DPT_TRIANGLELIST, vOffset, 0, vCount, 0, vCount / 2); + //HW.pDevice->SetRenderState (D3DRS_CULLMODE,D3DCULL_CCW); + RCache.set_CullMode(CULL_CCW); + } + + // Particles + CEffect_Rain::Particle* P = owner.particle_active; + if (0 == P) return; + + { + float dt = Device.fTimeDelta; + _IndexStream& _IS = RCache.Index; + RCache.set_Shader(DM_Drop->shader); + + Fmatrix mXform, mScale; + int pcount = 0; + u32 v_offset, i_offset; + u32 vCount_Lock = particles_cache*DM_Drop->number_vertices; + u32 iCount_Lock = particles_cache*DM_Drop->number_indices; + IRender_DetailModel::fvfVertexOut* v_ptr = (IRender_DetailModel::fvfVertexOut*) RCache.Vertex.Lock(vCount_Lock, hGeom_Drops->vb_stride, v_offset); + u16* i_ptr = _IS.Lock(iCount_Lock, i_offset); + while (P) { + CEffect_Rain::Particle* next = P->next; + + // Update + // P can be zero sometimes and it crashes + P->time -= dt; + if (P->time<0) { + owner.p_free(P); + P = next; + continue; + } + + // Render + if (::Render->ViewBase.testSphere_dirty(P->bounds.P, P->bounds.R)) + { + // Build matrix + float scale = P->time / particles_time; + mScale.scale(scale, scale, scale); + mXform.mul_43(P->mXForm, mScale); + + // XForm verts + DM_Drop->transfer(mXform, v_ptr, u_rain_color, i_ptr, pcount*DM_Drop->number_vertices); + v_ptr += DM_Drop->number_vertices; + i_ptr += DM_Drop->number_indices; + pcount++; + + if (pcount >= particles_cache) { + // flush + u32 dwNumPrimitives = iCount_Lock / 3; + RCache.Vertex.Unlock(vCount_Lock, hGeom_Drops->vb_stride); + _IS.Unlock(iCount_Lock); + RCache.set_Geometry(hGeom_Drops); + RCache.Render(D3DPT_TRIANGLELIST, v_offset, 0, vCount_Lock, i_offset, dwNumPrimitives); + + v_ptr = (IRender_DetailModel::fvfVertexOut*) RCache.Vertex.Lock(vCount_Lock, hGeom_Drops->vb_stride, v_offset); + i_ptr = _IS.Lock(iCount_Lock, i_offset); + + pcount = 0; + } + } + + P = next; + } + + // Flush if needed + vCount_Lock = pcount*DM_Drop->number_vertices; + iCount_Lock = pcount*DM_Drop->number_indices; + u32 dwNumPrimitives = iCount_Lock / 3; + RCache.Vertex.Unlock(vCount_Lock, hGeom_Drops->vb_stride); + _IS.Unlock(iCount_Lock); + if (pcount) { + RCache.set_Geometry(hGeom_Drops); + RCache.Render(D3DPT_TRIANGLELIST, v_offset, 0, vCount_Lock, i_offset, dwNumPrimitives); + } + } +} + +const Fsphere& glRainRender::GetDropBounds() const +{ + return DM_Drop->bv_sphere; +} diff --git a/src/Layers/xrRenderPC_GL/glRainRender.h b/src/Layers/xrRenderPC_GL/glRainRender.h new file mode 100644 index 00000000000..ff32604e0e6 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glRainRender.h @@ -0,0 +1,26 @@ +#pragma once + +#include "../../include/xrRender/RainRender.h" + +class glRainRender : + public IRainRender +{ +public: + glRainRender(); + virtual ~glRainRender(); + virtual void Copy(IRainRender &_in); + + virtual void Render(CEffect_Rain &owner); + + virtual const Fsphere& GetDropBounds() const; + +private: + // Visualization (rain) + ref_shader SH_Rain; + ref_geom hGeom_Rain; + + // Visualization (drops) + IRender_DetailModel* DM_Drop; + ref_geom hGeom_Drops; +}; + diff --git a/src/Layers/xrRenderPC_GL/glRenderDeviceRender.cpp b/src/Layers/xrRenderPC_GL/glRenderDeviceRender.cpp new file mode 100644 index 00000000000..31d0cbc9d7b --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glRenderDeviceRender.cpp @@ -0,0 +1,466 @@ +#include "stdafx.h" +#include "glRenderDeviceRender.h" + +#include + +#ifndef _EDITOR +void fill_vid_mode_list(); +void free_vid_mode_list(); +#else +void fill_vid_mode_list() {} +void free_vid_mode_list() {} +#endif + +void CALLBACK glRenderDeviceRender::OnDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, + GLsizei length, const GLchar* message, const void* userParam) +{ + if (severity != GL_DEBUG_SEVERITY_NOTIFICATION) + Log(message, id); +} + +glRenderDeviceRender::glRenderDeviceRender() + : m_hWnd(NULL) + , m_hDC(NULL) + , m_hRC(NULL) + , Resources(nullptr) +{ +} + +void glRenderDeviceRender::OnDeviceCreate(LPCSTR shName) +{ + // Signal everyone - device created + RCache.OnDeviceCreate(); + Resources->OnDeviceCreate(shName); + ::Render->create(); + Device.Statistic->OnDeviceCreate(); + + //#ifndef DEDICATED_SERVER + if (!g_dedicated_server) + { + m_WireShader.create("editor\\wire"); + m_SelectionShader.create("editor\\selection"); + + //DUImpl.OnDeviceCreate(); + } + //#endif +} + +bool glRenderDeviceRender::Create(HWND hWnd, u32 &dwWidth, u32 &dwHeight, float &fWidth_2, float &fHeight_2, bool move_window) +{ + m_hWnd = hWnd; + if (m_hWnd == NULL) + return false; + + m_move_window = move_window; + +#ifndef _EDITOR + updateWindowProps(); + fill_vid_mode_list(); +#endif + + RECT rClient = { 0 }; + + if (!GetClientRect(m_hWnd, &rClient)) + return false; + + dwWidth = (rClient.right - rClient.left); + dwHeight = (rClient.bottom - rClient.top); + fWidth_2 = float(dwWidth / 2); + fHeight_2 = float(dwHeight / 2); + + PIXELFORMATDESCRIPTOR pfd = + { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | + PFD_SUPPORT_OPENGL | + PFD_DOUBLEBUFFER, // Flags + PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. + 32, // Color depth of the framebuffer. + 0, 0, 0, 0, 0, 0, + 0, + 0, + 0, + 0, 0, 0, 0, + 24, // Number of bits for the depthbuffer + 8, // Number of bits for the stencilbuffer + 0, // Number of Aux buffers in the framebuffer. + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + // Get the device context + m_hDC = GetDC(hWnd); + if (m_hDC == NULL) + { + Msg("Could not get device context."); + return false; + } + + // Choose the closest pixel format + int iPixelFormat = ChoosePixelFormat(m_hDC, &pfd); + if (iPixelFormat == 0) + { + Msg("No pixel format found."); + return false; + } + + // Apply the pixel format to the device context + if (!SetPixelFormat(m_hDC, iPixelFormat, &pfd)) + { + Msg("Could not set pixel format."); + return false; + } + + // Create the context + m_hRC = wglCreateContext(m_hDC); + if (m_hRC == NULL) + { + Msg("Could not create drawing context."); + return false; + } + + // Make the new context the current context for this thread + // NOTE: This assumes the thread calling Create() is the only + // thread that will use the context. + if (!wglMakeCurrent(m_hDC, m_hRC)) + { + Msg("Could not make context current."); + return false; + } + + // Initialize OpenGL Extension Wrangler + if (glewInit() != GLEW_OK) + { + Msg("Could not initialize glew."); + return false; + } + +#ifdef DEBUG + CHK_GL(glEnable(GL_DEBUG_OUTPUT)); + CHK_GL(glDebugMessageCallback((GLDEBUGPROC)OnDebugCallback, nullptr)); +#endif // DEBUG + + updateViews(); + + Resources = new CResourceManager(); + + return true; +} + +void glRenderDeviceRender::DestroyHW() +{ + xr_delete(Resources); + + if (m_hRC) + { + if (!wglMakeCurrent(nullptr, nullptr)) + Msg("Could not release drawing context."); + + if (!wglDeleteContext(m_hRC)) + Msg("Could not delete context."); + + m_hRC = nullptr; + } + + if (m_hDC) + { + if (!ReleaseDC(m_hWnd, m_hDC)) + Msg("Could not release device context."); + + m_hDC = nullptr; + } + +#ifndef _EDITOR + free_vid_mode_list(); +#endif +} + +void glRenderDeviceRender::SetupStates() +{ + HW.Caps.Update(); + + // TODO: OGL: Implement Resetting of render states into default mode + //VERIFY(!"glRenderDeviceRender::SetupStates not implemented."); +} + +void glRenderDeviceRender::DeferredLoad(BOOL E) +{ + Resources->DeferredLoad(E); +} + +void glRenderDeviceRender::ResourcesDeferredUpload() +{ + Resources->DeferredUpload(); +} + +void glRenderDeviceRender::ResourcesGetMemoryUsage(u32& m_base, u32& c_base, u32& m_lmaps, u32& c_lmaps) +{ + if (Resources) + Resources->_GetMemoryUsage(m_base, c_base, m_lmaps, c_lmaps); +} + +void glRenderDeviceRender::ResourcesDestroyNecessaryTextures() +{ + Resources->DestroyNecessaryTextures(); +} + +void glRenderDeviceRender::ResourcesStoreNecessaryTextures() +{ + glRenderDeviceRender::Instance().Resources->StoreNecessaryTextures(); +} + +void glRenderDeviceRender::ResourcesDumpMemoryUsage() +{ + glRenderDeviceRender::Instance().Resources->_DumpMemoryUsage(); +} + +void glRenderDeviceRender::ClearTarget() +{ + Clear(0, 0, + D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL | + (psDeviceFlags.test(rsClearBB) ? D3DCLEAR_TARGET : 0), + color_xrgb(0, 0, 0), 1, 0 + ); +} + +HRESULT glRenderDeviceRender::Clear(DWORD Count, const D3DRECT *pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) +{ + // TODO: OGL: Implement support for clearing rectangles. + R_ASSERT(Count == 0 && pRects == NULL); + + GLbitfield mask = 0; + if (Flags & D3DCLEAR_TARGET) + mask |= GL_COLOR_BUFFER_BIT; + if (Flags & D3DCLEAR_ZBUFFER) + mask |= GL_DEPTH_BUFFER_BIT; + if (Flags & D3DCLEAR_STENCIL) + mask |= GL_STENCIL_BUFFER_BIT; + + + glPushAttrib(mask); + + if (Flags & D3DCLEAR_TARGET) + { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glClearColor( + color_get_R(Color) / 255.0f, + color_get_G(Color) / 255.0f, + color_get_B(Color) / 255.0f, + color_get_A(Color) / 255.0f); + } + + if (Flags & D3DCLEAR_ZBUFFER) + { + glDepthMask(GL_TRUE); + glClearDepthf(Z); + } + + if (Flags & D3DCLEAR_STENCIL) + { + glStencilMask(~0); + glClearStencil(Stencil); + } + + CHK_GL(glClear(mask)); + glPopAttrib(); + + return S_OK; +} + +void glRenderDeviceRender::SetCacheXform(Fmatrix &mView, Fmatrix &mProject) +{ + RCache.set_xform_view(mView); + RCache.set_xform_project(mProject); +} + +void glRenderDeviceRender::Begin() +{ + RCache.OnFrameBegin(); + RCache.set_CullMode(CULL_CW); + RCache.set_CullMode(CULL_CCW); +} + +void glRenderDeviceRender::End() +{ + RCache.OnFrameEnd(); + Memory.dbg_check(); + SwapBuffers(m_hDC); +} + +void glRenderDeviceRender::Reset(HWND hWnd, u32 &dwWidth, u32 &dwHeight, float &fWidth_2, float &fHeight_2) +{ + // We should still be rendering to the same window. + R_ASSERT(m_hWnd == hWnd); + Resources->reset_begin(); + Memory.mem_compact(); + + dwWidth = psCurrentVidMode[0]; + dwHeight = psCurrentVidMode[1]; + + CHK_GL(glDeleteTextures(1, &HW.pBaseZB)); + + updateViews(); + updateWindowProps(); + + fWidth_2 = float(dwWidth / 2); + fHeight_2 = float(dwHeight / 2); + Resources->reset_end(); +} + +void glRenderDeviceRender::OnAssetsChanged() +{ + Resources->m_textures_description.UnLoad(); + Resources->m_textures_description.Load(); +} + +void glRenderDeviceRender::updateViews() +{ + // Create an staging depth buffer used for post-processing + glGenTextures(1, &HW.pBaseZB); + CHK_GL(glBindTexture(GL_TEXTURE_2D, HW.pBaseZB)); + CHK_GL(glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, Device.dwWidth, Device.dwHeight)); +} + +void glRenderDeviceRender::updateWindowProps() +{ + // BOOL bWindowed = strstr(Core.Params,"-dedicated") ? TRUE : !psDeviceFlags.is (rsFullscreen); + BOOL bWindowed = !psDeviceFlags.is(rsFullscreen); + + u32 dwWindowStyle = 0; + // Set window properties depending on what mode were in. + if (bWindowed) { + if (strstr(Core.Params, "-no_dialog_header")) + SetWindowLong(m_hWnd, GWL_STYLE, dwWindowStyle = (WS_BORDER | WS_VISIBLE)); + else + SetWindowLong(m_hWnd, GWL_STYLE, dwWindowStyle = (WS_BORDER | WS_DLGFRAME | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX)); + + // Change to default resolution + ChangeDisplaySettings(nullptr, CDS_FULLSCREEN); + } + else { + SetWindowLong(m_hWnd, GWL_STYLE, dwWindowStyle = (WS_POPUP | WS_VISIBLE)); + + DEVMODE dmScreenSettings; + memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); + dmScreenSettings.dmSize = sizeof(dmScreenSettings); + dmScreenSettings.dmPelsWidth = psCurrentVidMode[0]; + dmScreenSettings.dmPelsHeight = psCurrentVidMode[1]; + dmScreenSettings.dmBitsPerPel = 32; + dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + + // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. + ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN); + } + + if (m_move_window) { + // When moving from fullscreen to windowed mode, it is important to + // adjust the window size after recreating the device rather than + // beforehand to ensure that you get the window size you want. For + // example, when switching from 640x480 fullscreen to windowed with + // a 1000x600 window on a 1024x768 desktop, it is impossible to set + // the window size to 1000x600 until after the display mode has + // changed to 1024x768, because windows cannot be larger than the + // desktop. + + RECT m_rcWindowBounds; + BOOL bCenter = FALSE; + if (strstr(Core.Params, "-center_screen")) bCenter = TRUE; + + if (bCenter) { + RECT DesktopRect; + + GetClientRect(GetDesktopWindow(), &DesktopRect); + + SetRect(&m_rcWindowBounds, + (DesktopRect.right - psCurrentVidMode[0]) / 2, + (DesktopRect.bottom - psCurrentVidMode[1]) / 2, + (DesktopRect.right + psCurrentVidMode[0]) / 2, + (DesktopRect.bottom + psCurrentVidMode[1]) / 2); + } + else { + SetRect(&m_rcWindowBounds, + 0, + 0, + psCurrentVidMode[0], + psCurrentVidMode[1]); + } + + AdjustWindowRect(&m_rcWindowBounds, dwWindowStyle, FALSE); + + SetWindowPos(m_hWnd, + HWND_TOP, + m_rcWindowBounds.left, + m_rcWindowBounds.top, + (m_rcWindowBounds.right - m_rcWindowBounds.left), + (m_rcWindowBounds.bottom - m_rcWindowBounds.top), + SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_DRAWFRAME); + } + + ShowCursor(FALSE); + SetForegroundWindow(m_hWnd); +} + +struct _uniq_mode +{ + _uniq_mode(LPCSTR v) :_val(v){} + LPCSTR _val; + bool operator() (LPCSTR _other) { return !stricmp(_val, _other); } +}; + +void free_vid_mode_list() +{ + for (int i = 0; vid_mode_token[i].name; i++) + { + xr_free(vid_mode_token[i].name); + } + xr_free(vid_mode_token); + vid_mode_token = NULL; +} + +void fill_vid_mode_list() +{ + if (vid_mode_token != NULL) return; + xr_vector _tmp; + + DWORD iModeNum = 0; + DEVMODE dmi; + ZeroMemory(&dmi, sizeof(dmi)); + dmi.dmSize = sizeof(dmi); + + while (EnumDisplaySettings(nullptr, iModeNum++, &dmi) != 0) + { + string32 str; + + if (dmi.dmPelsWidth < 800) + continue; + + sprintf_s(str, sizeof(str), "%dx%d", dmi.dmPelsWidth, dmi.dmPelsHeight); + + if (_tmp.end() != std::find_if(_tmp.begin(), _tmp.end(), _uniq_mode(str))) + continue; + + _tmp.push_back(NULL); + _tmp.back() = xr_strdup(str); + } + + u32 _cnt = _tmp.size() + 1; + + vid_mode_token = xr_alloc(_cnt); + + vid_mode_token[_cnt - 1].id = -1; + vid_mode_token[_cnt - 1].name = NULL; + +#ifdef DEBUG + Msg("Available video modes[%d]:", _tmp.size()); +#endif // DEBUG + for (u32 i = 0; i<_tmp.size(); ++i) + { + vid_mode_token[i].id = i; + vid_mode_token[i].name = _tmp[i]; +#ifdef DEBUG + Msg("[%s]", _tmp[i]); +#endif // DEBUG + } +} diff --git a/src/Layers/xrRenderPC_GL/glRenderDeviceRender.h b/src/Layers/xrRenderPC_GL/glRenderDeviceRender.h new file mode 100644 index 00000000000..41868f9c106 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glRenderDeviceRender.h @@ -0,0 +1,82 @@ +#pragma once + +#include "..\..\Include\xrRender\RenderDeviceRender.h" + +#ifndef _EDITOR + #define DEV glRenderDeviceRender::Instance().Resources +#else + #define DEV Device.Resources +#endif + +class CResourceManager; + +class glRenderDeviceRender : + public IRenderDeviceRender +{ +public: + static glRenderDeviceRender& Instance() { return *((glRenderDeviceRender*)(&*Device.m_pRender)); } + + glRenderDeviceRender(); + + virtual void Copy(IRenderDeviceRender &_in) { VERIFY(!"glRenderDeviceRender::Copy not implemented."); }; + + // Gamma correction functions + virtual void setGamma(float fGamma) { /* TODO: OGL: VERIFY(!"glRenderDeviceRender::setGamma not implemented."); */ }; + virtual void setBrightness(float fGamma) { /* TODO: OGL: VERIFY(!"glRenderDeviceRender::setBrightness not implemented."); */ }; + virtual void setContrast(float fGamma) { /* TODO: OGL: VERIFY(!"glRenderDeviceRender::setContrast not implemented."); */ }; + virtual void updateGamma() { /* TODO: OGL: VERIFY(!"glRenderDeviceRender::updateGamma not implemented."); */ }; + + // Destroy + virtual void OnDeviceDestroy(BOOL bKeepTextures) { VERIFY(!"glRenderDeviceRender::OnDeviceDestroy not implemented."); }; + virtual void ValidateHW() { VERIFY(!"glRenderDeviceRender::ValidateHW not implemented."); }; + virtual void DestroyHW(); + virtual void Reset(HWND hWnd, u32 &dwWidth, u32 &dwHeight, float &fWidth_2, float &fHeight_2); + // Init + virtual void SetupStates(); + virtual void OnDeviceCreate(LPCSTR shName); + virtual bool Create(HWND hWnd, u32 &dwWidth, u32 &dwHeight, float &fWidth_2, float &fHeight_2, bool move_window); + virtual void SetupGPU(BOOL bForceGPU_SW, BOOL bForceGPU_NonPure, BOOL bForceGPU_REF) { }; + // Overdraw + virtual void overdrawBegin() { VERIFY(!"glRenderDeviceRender::overdrawBegin not implemented."); }; + virtual void overdrawEnd() { VERIFY(!"glRenderDeviceRender::overdrawEnd not implemented."); }; + + // Resources control + virtual void DeferredLoad(BOOL E); + virtual void ResourcesDeferredUpload(); + virtual void ResourcesGetMemoryUsage(u32& m_base, u32& c_base, u32& m_lmaps, u32& c_lmaps); + virtual void ResourcesDestroyNecessaryTextures(); + virtual void ResourcesStoreNecessaryTextures(); + virtual void ResourcesDumpMemoryUsage(); + + // HWSupport + virtual bool HWSupportsShaderYUV2RGB() { return true; }; + HRESULT Clear(DWORD Count, const D3DRECT *pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil); + + // Device state + virtual DeviceState GetDeviceState() { return dsOK; }; + virtual BOOL GetForceGPU_REF() { return false; }; + virtual u32 GetCacheStatPolys() { VERIFY(!"glRenderDeviceRender::GetCacheStatPolys not implemented."); return 0; }; + virtual void Begin(); + virtual void Clear() { VERIFY(!"glRenderDeviceRender::Clear not implemented."); }; + virtual void End(); + virtual void ClearTarget(); + virtual void SetCacheXform(Fmatrix &mView, Fmatrix &mProject); + virtual void OnAssetsChanged(); + +public: + CResourceManager* Resources; + ref_shader m_WireShader; + ref_shader m_SelectionShader; + +private: + bool m_move_window; + HWND m_hWnd; + HDC m_hDC; + HGLRC m_hRC; + + void updateWindowProps(); + void updateViews(); + + static void CALLBACK glRenderDeviceRender::OnDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, + GLsizei length, const GLchar* message, const void* userParam); +}; diff --git a/src/Layers/xrRenderPC_GL/glRenderFactory.cpp b/src/Layers/xrRenderPC_GL/glRenderFactory.cpp new file mode 100644 index 00000000000..dab6f349a25 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glRenderFactory.cpp @@ -0,0 +1,74 @@ +#include "stdafx.h" +#include "glRenderFactory.h" + +//#include "glStatGraphRender.h" +#ifndef _EDITOR + #include "glLensFlareRender.h" +#endif +//#include "glConsoleRender.h" +#ifndef _EDITOR + #include "glThunderboltRender.h" + #include "glThunderboltDescRender.h" + #include "glRainRender.h" + #include "glLensFlareRender.h" + #include "glEnvironmentRender.h" + + #include "glRenderDeviceRender.h" + #include "glObjectSpaceRender.h" +#endif // _EDITOR + +#include "glFontRender.h" +#include "glApplicationRender.h" +#include "glWallMarkArray.h" +#include "glStatsRender.h" +#include "glUISequenceVideoItem.h" +#include "glUIShader.h" + +glRenderFactory RenderFactoryImpl; + +//# include "gl##Class.h" \ + +#define RENDER_FACTORY_IMPLEMENT(Class) \ + I##Class* glRenderFactory::Create##Class() \ +{ \ + return new gl##Class(); \ +} \ + void glRenderFactory::Destroy##Class(I##Class *pObject)\ +{ \ + xr_delete((gl##Class*&)pObject); \ +} \ + +#define RENDER_FACTORY_UNIMPLEMENT(Class) \ + I##Class* glRenderFactory::Create##Class() \ +{ \ + VERIFY(!#Class" not implemented."); return nullptr; \ +} \ + void glRenderFactory::Destroy##Class(I##Class *pObject)\ +{ \ +} \ + +#ifndef _EDITOR + RENDER_FACTORY_IMPLEMENT(UISequenceVideoItem) + RENDER_FACTORY_IMPLEMENT(UIShader) + RENDER_FACTORY_UNIMPLEMENT(StatGraphRender) + RENDER_FACTORY_UNIMPLEMENT(ConsoleRender) + RENDER_FACTORY_IMPLEMENT(RenderDeviceRender) +# ifdef DEBUG + RENDER_FACTORY_IMPLEMENT(ObjectSpaceRender) +# endif // DEBUG + RENDER_FACTORY_IMPLEMENT(ApplicationRender) + RENDER_FACTORY_IMPLEMENT(WallMarkArray) + RENDER_FACTORY_IMPLEMENT(StatsRender) +#endif // _EDITOR + +#ifndef _EDITOR + RENDER_FACTORY_IMPLEMENT(ThunderboltRender) + RENDER_FACTORY_IMPLEMENT(ThunderboltDescRender) + RENDER_FACTORY_IMPLEMENT(RainRender) + RENDER_FACTORY_IMPLEMENT(LensFlareRender) + RENDER_FACTORY_IMPLEMENT(EnvironmentRender) + RENDER_FACTORY_IMPLEMENT(EnvDescriptorMixerRender) + RENDER_FACTORY_IMPLEMENT(EnvDescriptorRender) + RENDER_FACTORY_IMPLEMENT(FlareRender) +#endif +RENDER_FACTORY_IMPLEMENT(FontRender) diff --git a/src/Layers/xrRenderPC_GL/glRenderFactory.h b/src/Layers/xrRenderPC_GL/glRenderFactory.h new file mode 100644 index 00000000000..9e9f747d5ef --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glRenderFactory.h @@ -0,0 +1,38 @@ +#pragma once + +#include "..\..\Include\xrRender\RenderFactory.h" + +#define RENDER_FACTORY_DECLARE(Class) \ + virtual I##Class* Create##Class(); \ + virtual void Destroy##Class(I##Class *pObject); + +class glRenderFactory : public IRenderFactory +{ +#ifndef _EDITOR + RENDER_FACTORY_DECLARE(UISequenceVideoItem) + RENDER_FACTORY_DECLARE(UIShader) + RENDER_FACTORY_DECLARE(StatGraphRender) + RENDER_FACTORY_DECLARE(ConsoleRender) + RENDER_FACTORY_DECLARE(RenderDeviceRender) +# ifdef DEBUG + RENDER_FACTORY_DECLARE(ObjectSpaceRender) +# endif // DEBUG + RENDER_FACTORY_DECLARE(ApplicationRender) + RENDER_FACTORY_DECLARE(WallMarkArray) + RENDER_FACTORY_DECLARE(StatsRender) +#endif // _EDITOR + +#ifndef _EDITOR + RENDER_FACTORY_DECLARE(FlareRender) + RENDER_FACTORY_DECLARE(ThunderboltRender) + RENDER_FACTORY_DECLARE(ThunderboltDescRender) + RENDER_FACTORY_DECLARE(RainRender) + RENDER_FACTORY_DECLARE(LensFlareRender) + RENDER_FACTORY_DECLARE(EnvironmentRender) + RENDER_FACTORY_DECLARE(EnvDescriptorMixerRender) + RENDER_FACTORY_DECLARE(EnvDescriptorRender) +#endif + RENDER_FACTORY_DECLARE(FontRender) +}; + +extern glRenderFactory RenderFactoryImpl; diff --git a/src/Layers/xrRenderPC_GL/glResourceManager_Resources.cpp b/src/Layers/xrRenderPC_GL/glResourceManager_Resources.cpp new file mode 100644 index 00000000000..6ccffe7b0e1 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glResourceManager_Resources.cpp @@ -0,0 +1,627 @@ +#include "stdafx.h" +#pragma hdrstop + +#ifndef _EDITOR +#include "../../xrEngine/render.h" +#endif + +#include "../xrRender/ResourceManager.h" +#include "../xrRender/tss.h" +#include "../xrRender/blenders\blender.h" +#include "../xrRender/blenders\blender_recorder.h" + +#include "../xrRenderGL/glBufferUtils.h" + +void fix_texture_name(LPSTR fn); + +void simplify_texture(string_path &fn) +{ + if (strstr(Core.Params,"-game_designer")) + { + if (strstr(fn, "$user")) return; + if (strstr(fn, "ui\\")) return; + if (strstr(fn, "lmap#")) return; + if (strstr(fn, "act\\")) return; + if (strstr(fn, "fx\\")) return; + if (strstr(fn, "glow\\")) return; + if (strstr(fn, "map\\")) return; + strcpy_s( fn, "ed\\ed_not_existing_texture" ); + } +} + + +template +BOOL reclaim (xr_vector& vec, const T* ptr) +{ + xr_vector::iterator it = vec.begin (); + xr_vector::iterator end = vec.end (); + for (; it!=end; it++) + if (*it == ptr) { vec.erase (it); return TRUE; } + return FALSE; +} + + +//-------------------------------------------------------------------------------------------------------------- +SState* CResourceManager::_CreateState (SimulatorStates& state_code) +{ + // Search equal state-code + for (u32 it=0; itstate_code; + if (base.equal(state_code)) return C; + } + + // Create New + SState* S = new SState(); + v_states.push_back (S); + state_code.record (S->state); + S->dwFlags |= xr_resource_flagged::RF_REGISTERED; + S->state_code = state_code; + return v_states.back(); +} +void CResourceManager::_DeleteState (const SState* state) +{ + if (0==(state->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + if (reclaim(v_states,state)) return; + Msg ("! ERROR: Failed to find compiled stateblock"); +} + +//-------------------------------------------------------------------------------------------------------------- +SPass* CResourceManager::_CreatePass (ref_state& _state, ref_ps& _ps, ref_vs& _vs, ref_ctable& _ctable, ref_texture_list& _T, ref_matrix_list& _M, ref_constant_list& _C) +{ + for (u32 it=0; itequal(_state,_ps,_vs,_ctable,_T,_M,_C)) + return v_passes[it]; + + SPass* P = new SPass(); + P->dwFlags |= xr_resource_flagged::RF_REGISTERED; + P->state = _state; + P->ps = _ps; + P->vs = _vs; + P->constants = _ctable; + P->T = _T; +#ifdef _EDITOR + P->M = _M; +#endif + P->C = _C; + + v_passes.push_back (P); + return v_passes.back(); +} + +void CResourceManager::_DeletePass (const SPass* P) +{ + if (0==(P->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + if (reclaim(v_passes,P)) return; + Msg ("! ERROR: Failed to find compiled pass"); +} + +//-------------------------------------------------------------------------------------------------------------- +static BOOL dcl_equal (D3DVERTEXELEMENT9* a, D3DVERTEXELEMENT9* b) +{ + // check sizes + u32 a_size = glBufferUtils::GetDeclLength(a); + u32 b_size = glBufferUtils::GetDeclLength(b); + if (a_size != b_size) return FALSE; + return 0 == memcmp(a, b, a_size*sizeof(D3DVERTEXELEMENT9)); +} + +SDeclaration* CResourceManager::_CreateDecl (u32 FVF) +{ + // Search equal code + for (u32 it = 0; itdcl_code.empty() && D->FVF == FVF) return D; + } + + SDeclaration* D = new SDeclaration(); + glGenVertexArrays(1, &D->vao); + + D->FVF = FVF; + glBufferUtils::ConvertVertexDeclaration(FVF, D->vao); + D->dwFlags |= xr_resource_flagged::RF_REGISTERED; + v_declarations.push_back(D); + + return D; +} + +SDeclaration* CResourceManager::_CreateDecl(D3DVERTEXELEMENT9* dcl) +{ + // Search equal code + for (u32 it = 0; itdcl_code.empty() && dcl_equal(dcl, &*D->dcl_code.begin())) return D; + } + + SDeclaration* D = new SDeclaration(); + glGenVertexArrays(1, &D->vao); + + D->FVF = 0; + u32 dcl_size = glBufferUtils::GetDeclLength(dcl) + 1; + D->dcl_code.assign(dcl, dcl + dcl_size); + glBufferUtils::ConvertVertexDeclaration(dcl, D->vao); + D->dwFlags |= xr_resource_flagged::RF_REGISTERED; + v_declarations.push_back(D); + + return D; +} + +void CResourceManager::_DeleteDecl (const SDeclaration* dcl) +{ + if (0==(dcl->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + if (reclaim(v_declarations,dcl)) return; + Msg ("! ERROR: Failed to find compiled vertex-declarator"); +} + +//-------------------------------------------------------------------------------------------------------------- +SVS* CResourceManager::_CreateVS (LPCSTR _name) +{ + string_path name; + strcpy_s(name, _name); + if (0 == ::Render->m_skinning) strcat(name, "_0"); + if (1 == ::Render->m_skinning) strcat(name, "_1"); + if (2 == ::Render->m_skinning) strcat(name, "_2"); + if (3 == ::Render->m_skinning) strcat(name, "_3"); + if (4 == ::Render->m_skinning) strcat(name, "_4"); + LPSTR N = LPSTR(name); + map_VS::iterator I = m_vs.find(N); + if (I != m_vs.end()) return I->second; + else + { + SVS* _vs = new SVS(); + _vs->dwFlags |= xr_resource_flagged::RF_REGISTERED; + m_vs.insert(mk_pair(_vs->set_name(name), _vs)); + //_vs->vs = NULL; + //_vs->signature = NULL; + VERIFY(strcmpi(name, "null") != 0); + + GLchar* pErrorBuf = NULL; + string_path cname; + strconcat(sizeof(cname), cname, ::Render->getShaderPath(), _name, ".vs"); + FS.update_path(cname, "$game_shaders$", cname); + // LPCSTR target = NULL; + + IReader* fs = FS.r_open(cname); + // TODO: OGL: HACK: Implement all shaders. Remove this for PS + if (!fs) + { + string1024 tmp; + sprintf(tmp, "OGL: %s is missing. Replace with stub_default.vs", cname); + Msg(tmp); + strconcat(sizeof(cname), cname, ::Render->getShaderPath(), "stub_default", ".vs"); + FS.update_path(cname, "$game_shaders$", cname); + fs = FS.r_open(cname); + } + R_ASSERT3(fs, "shader file doesnt exist", cname); + + // vertex + R_ASSERT2(fs, cname); + _vs->vs = glCreateShader(GL_VERTEX_SHADER); + GLenum _result = ::Render->shader_compile(name, LPCSTR(fs->pointer()), fs->length(), NULL, NULL, NULL, NULL, 0, &_vs->vs, &pErrorBuf, NULL); + FS.r_close(fs); + + if (_result == GL_TRUE) + { + // Parse constant, texture, sampler binding + _vs->constants.parse(&_vs->vs, RC_dest_vertex); + } + else + { + VERIFY(pErrorBuf); + Log("! VS: ", _name); + Log("! error: ", pErrorBuf); + } + R_ASSERT2(_result, pErrorBuf); + xr_free(pErrorBuf); + return _vs; + } +} + +void CResourceManager::_DeleteVS (const SVS* vs) +{ + if (0==(vs->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + LPSTR N = LPSTR (*vs->cName); + map_VS::iterator I = m_vs.find (N); + if (I!=m_vs.end()) { + m_vs.erase(I); + return; + } + Msg ("! ERROR: Failed to find compiled vertex-shader '%s'",*vs->cName); +} + +//-------------------------------------------------------------------------------------------------------------- +SPS* CResourceManager::_CreatePS (LPCSTR _name) +{ + string_path name; + strcpy_s(name, _name); + if (0 == ::Render->m_MSAASample) strcat(name, "_0"); + if (1 == ::Render->m_MSAASample) strcat(name, "_1"); + if (2 == ::Render->m_MSAASample) strcat(name, "_2"); + if (3 == ::Render->m_MSAASample) strcat(name, "_3"); + if (4 == ::Render->m_MSAASample) strcat(name, "_4"); + if (5 == ::Render->m_MSAASample) strcat(name, "_5"); + if (6 == ::Render->m_MSAASample) strcat(name, "_6"); + if (7 == ::Render->m_MSAASample) strcat(name, "_7"); + LPSTR N = LPSTR(name); + map_PS::iterator I = m_ps.find(N); + if (I != m_ps.end()) return I->second; + else + { + SPS* _ps = new SPS(); + _ps->dwFlags |= xr_resource_flagged::RF_REGISTERED; + m_ps.insert(mk_pair(_ps->set_name(name), _ps)); + VERIFY(strcmpi(name, "null") != 0); + + // Open file + string_path cname; + strconcat(sizeof(cname), cname, ::Render->getShaderPath(), _name, ".ps"); + FS.update_path(cname, "$game_shaders$", cname); + + // duplicate and zero-terminate + IReader* R = FS.r_open(cname); + // TODO: DX10: HACK: Implement all shaders. Remove this for PS + if (!R) + { + string1024 tmp; + // TODO: HACK: Test failure + //Memory.mem_compact(); + sprintf(tmp, "OGL: %s is missing. Replace with stub_default.ps", cname); + Msg(tmp); + strconcat(sizeof(cname), cname, ::Render->getShaderPath(), "stub_default", ".ps"); + FS.update_path(cname, "$game_shaders$", cname); + R = FS.r_open(cname); + } + R_ASSERT2(R, cname); + u32 size = R->length(); + char* data = xr_alloc(size + 1); + CopyMemory(data, R->pointer(), size); + data[size] = 0; + FS.r_close(R); + + // Compile + GLchar* pErrorBuf = NULL; + _ps->ps = glCreateShader(GL_FRAGMENT_SHADER); + GLenum _result = ::Render->shader_compile(name, data, size, NULL, NULL, NULL, NULL, 0, &_ps->ps, &pErrorBuf, NULL); + xr_free(data); + + if (_result == GL_TRUE) + { + // Parse constant, texture, sampler binding + _ps->constants.parse(&_ps->ps, RC_dest_pixel); + } + else + { + VERIFY(pErrorBuf); + Log("! PS: ", _name); + Msg("error is %s", pErrorBuf); + } + R_ASSERT2(_result, pErrorBuf); + xr_free(pErrorBuf); + + if (_result == GL_FALSE) + Msg("Can't compile shader %s", _name); + + CHECK_OR_EXIT( + _result != GL_FALSE, + make_string("Your video card doesn't meet game requirements\n\nPixel Shaders v1.1 or higher required") + ); + return _ps; + } +} +void CResourceManager::_DeletePS (const SPS* ps) +{ + if (0==(ps->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + LPSTR N = LPSTR (*ps->cName); + map_PS::iterator I = m_ps.find (N); + if (I!=m_ps.end()) { + m_ps.erase(I); + return; + } + Msg ("! ERROR: Failed to find compiled pixel-shader '%s'",*ps->cName); +} + +R_constant_table* CResourceManager::_CreateConstantTable (R_constant_table& C) +{ + if (C.empty()) return NULL; + for (u32 it=0; itequal(C)) return v_constant_tables[it]; + v_constant_tables.push_back (new R_constant_table(C)); + v_constant_tables.back()->dwFlags |= xr_resource_flagged::RF_REGISTERED; + return v_constant_tables.back (); +} +void CResourceManager::_DeleteConstantTable (const R_constant_table* C) +{ + if (0==(C->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + if (reclaim(v_constant_tables,C)) return; + Msg ("! ERROR: Failed to find compiled constant-table"); +} + +//-------------------------------------------------------------------------------------------------------------- +CRT* CResourceManager::_CreateRT (LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount ) +{ + R_ASSERT(Name && Name[0] && w && h); + + // ***** first pass - search already created RT + LPSTR N = LPSTR(Name); + map_RT::iterator I = m_rtargets.find (N); + if (I!=m_rtargets.end()) return I->second; + else + { + CRT *RT = new CRT(); + RT->dwFlags |= xr_resource_flagged::RF_REGISTERED; + m_rtargets.insert (mk_pair(RT->set_name(Name),RT)); + if (Device.b_is_Ready) RT->create (Name,w,h,f); + return RT; + } +} +void CResourceManager::_DeleteRT (const CRT* RT) +{ + if (0==(RT->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + LPSTR N = LPSTR (*RT->cName); + map_RT::iterator I = m_rtargets.find (N); + if (I!=m_rtargets.end()) { + m_rtargets.erase(I); + return; + } + Msg ("! ERROR: Failed to find render-target '%s'",*RT->cName); +} + +//-------------------------------------------------------------------------------------------------------------- +void CResourceManager::DBG_VerifyGeoms () +{ +} + +SGeometry* CResourceManager::CreateGeom (D3DVERTEXELEMENT9* decl, GLuint vb, GLuint ib) +{ + R_ASSERT(decl && vb); + + SDeclaration* dcl = _CreateDecl(decl); + u32 vb_stride = glBufferUtils::GetDeclVertexSize(decl); + + // ***** first pass - search already loaded shader + for (u32 it = 0; itdwFlags |= xr_resource_flagged::RF_REGISTERED; + Geom->dcl = dcl; + Geom->vb = vb; + Geom->vb_stride = vb_stride; + Geom->ib = ib; + v_geoms.push_back(Geom); + return Geom; +} + +SGeometry* CResourceManager::CreateGeom (u32 FVF, GLuint vb, GLuint ib) +{ + R_ASSERT(FVF && vb); + + SDeclaration* dcl = _CreateDecl(FVF); + u32 vb_stride = glBufferUtils::GetFVFVertexSize(FVF); + + // ***** first pass - search already loaded shader + for (u32 it = 0; itdwFlags |= xr_resource_flagged::RF_REGISTERED; + Geom->dcl = dcl; + Geom->vb = vb; + Geom->vb_stride = vb_stride; + Geom->ib = ib; + v_geoms.push_back(Geom); + return Geom; +} + +void CResourceManager::DeleteGeom (const SGeometry* Geom) +{ + if (0==(Geom->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + if (reclaim(v_geoms,Geom)) return; + Msg ("! ERROR: Failed to find compiled geometry-declaration"); +} + +//-------------------------------------------------------------------------------------------------------------- +CTexture* CResourceManager::_CreateTexture (LPCSTR _Name) +{ + // DBG_VerifyTextures (); + if (0==xr_strcmp(_Name,"null")) return 0; + R_ASSERT (_Name && _Name[0]); + string_path Name; + strcpy_s (Name,_Name); //. andy if (strext(Name)) *strext(Name)=0; + fix_texture_name (Name); + +#ifdef DEBUG + simplify_texture(Name); +#endif // DEBUG + + // ***** first pass - search already loaded texture + LPSTR N = LPSTR(Name); + map_TextureIt I = m_textures.find (N); + if (I!=m_textures.end()) return I->second; + else + { + CTexture * T = new CTexture(); + T->dwFlags |= xr_resource_flagged::RF_REGISTERED; + m_textures.insert (mk_pair(T->set_name(Name),T)); + T->Preload (); + if (Device.b_is_Ready && !bDeferredLoad) T->Load(); + return T; + } +} +void CResourceManager::_DeleteTexture (const CTexture* T) +{ + // DBG_VerifyTextures (); + + if (0==(T->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + LPSTR N = LPSTR (*T->cName); + map_Texture::iterator I = m_textures.find (N); + if (I!=m_textures.end()) { + m_textures.erase(I); + return; + } + Msg ("! ERROR: Failed to find texture surface '%s'",*T->cName); +} + +#ifdef DEBUG +void CResourceManager::DBG_VerifyTextures () +{ + map_Texture::iterator I = m_textures.begin (); + map_Texture::iterator E = m_textures.end (); + for (; I!=E; I++) + { + R_ASSERT(I->first); + R_ASSERT(I->second); + R_ASSERT(I->second->cName); + R_ASSERT(0==xr_strcmp(I->first,*I->second->cName)); + } +} +#endif + +//-------------------------------------------------------------------------------------------------------------- +CMatrix* CResourceManager::_CreateMatrix (LPCSTR Name) +{ + R_ASSERT(Name && Name[0]); + if (0==stricmp(Name,"$null")) return NULL; + + LPSTR N = LPSTR(Name); + map_Matrix::iterator I = m_matrices.find (N); + if (I!=m_matrices.end()) return I->second; + else + { + CMatrix* M = new CMatrix(); + M->dwFlags |= xr_resource_flagged::RF_REGISTERED; + M->dwReference = 1; + m_matrices.insert (mk_pair(M->set_name(Name),M)); + return M; + } +} +void CResourceManager::_DeleteMatrix (const CMatrix* M) +{ + if (0==(M->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + LPSTR N = LPSTR (*M->cName); + map_Matrix::iterator I = m_matrices.find (N); + if (I!=m_matrices.end()) { + m_matrices.erase(I); + return; + } + Msg ("! ERROR: Failed to find xform-def '%s'",*M->cName); +} +void CResourceManager::ED_UpdateMatrix (LPCSTR Name, CMatrix* data) +{ + CMatrix* M = _CreateMatrix (Name); + *M = *data; +} +//-------------------------------------------------------------------------------------------------------------- +CConstant* CResourceManager::_CreateConstant (LPCSTR Name) +{ + R_ASSERT(Name && Name[0]); + if (0==stricmp(Name,"$null")) return NULL; + + LPSTR N = LPSTR(Name); + map_Constant::iterator I = m_constants.find (N); + if (I!=m_constants.end()) return I->second; + else + { + CConstant* C = new CConstant(); + C->dwFlags |= xr_resource_flagged::RF_REGISTERED; + C->dwReference = 1; + m_constants.insert (mk_pair(C->set_name(Name),C)); + return C; + } +} +void CResourceManager::_DeleteConstant (const CConstant* C) +{ + if (0==(C->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + LPSTR N = LPSTR (*C->cName); + map_Constant::iterator I = m_constants.find (N); + if (I!=m_constants.end()) { + m_constants.erase(I); + return; + } + Msg ("! ERROR: Failed to find R1-constant-def '%s'",*C->cName); +} + +void CResourceManager::ED_UpdateConstant (LPCSTR Name, CConstant* data) +{ + CConstant* C = _CreateConstant (Name); + *C = *data; +} + +//-------------------------------------------------------------------------------------------------------------- +bool cmp_tl (const std::pair& _1, const std::pair& _2) { + return _1.first < _2.first; +} +STextureList* CResourceManager::_CreateTextureList(STextureList& L) +{ + std::sort (L.begin(),L.end(),cmp_tl); + for (u32 it=0; itdwFlags |= xr_resource_flagged::RF_REGISTERED; + lst_textures.push_back (lst); + return lst; +} +void CResourceManager::_DeleteTextureList(const STextureList* L) +{ + if (0==(L->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + if (reclaim(lst_textures,L)) return; + Msg ("! ERROR: Failed to find compiled list of textures"); +} +//-------------------------------------------------------------------------------------------------------------- +SMatrixList* CResourceManager::_CreateMatrixList(SMatrixList& L) +{ + BOOL bEmpty = TRUE; + for (u32 i=0; idwFlags |= xr_resource_flagged::RF_REGISTERED; + lst_matrices.push_back (lst); + return lst; +} +void CResourceManager::_DeleteMatrixList ( const SMatrixList* L ) +{ + if (0==(L->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + if (reclaim(lst_matrices,L)) return; + Msg ("! ERROR: Failed to find compiled list of xform-defs"); +} +//-------------------------------------------------------------------------------------------------------------- +SConstantList* CResourceManager::_CreateConstantList(SConstantList& L) +{ + BOOL bEmpty = TRUE; + for (u32 i=0; idwFlags |= xr_resource_flagged::RF_REGISTERED; + lst_constants.push_back (lst); + return lst; +} +void CResourceManager::_DeleteConstantList(const SConstantList* L ) +{ + if (0==(L->dwFlags&xr_resource_flagged::RF_REGISTERED)) return; + if (reclaim(lst_constants,L)) return; + Msg ("! ERROR: Failed to find compiled list of r1-constant-defs"); +} diff --git a/src/Layers/xrRenderPC_GL/glResourceManager_Scripting.cpp b/src/Layers/xrRenderPC_GL/glResourceManager_Scripting.cpp new file mode 100644 index 00000000000..9623482c3cf --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glResourceManager_Scripting.cpp @@ -0,0 +1,356 @@ +#include "stdafx.h" +#pragma hdrstop + +#include + +#include "../../xrEngine/Render.h" +#include "../xrRender/ResourceManager.h" +#include "../xrRender/tss.h" +#include "../xrRender/blenders\blender.h" +#include "../xrRender/blenders\blender_recorder.h" +#include "../../xrEngine/ai_script_space.h" +#include "../../xrEngine/ai_script_lua_extension.h" +#include "luabind/return_reference_to_policy.hpp" + +#include "glRenderDeviceRender.h" + +using namespace luabind; + +#ifdef DEBUG +#define MDB Memory.dbg_check() +#else +#define MDB +#endif + +// wrapper +class adopt_sampler +{ + CBlender_Compile* C; + u32 stage; +public: + adopt_sampler (CBlender_Compile* _C, u32 _stage) : C(_C), stage(_stage) { if (u32(-1)==stage) C=0; } + adopt_sampler (const adopt_sampler& _C) : C(_C.C), stage(_C.stage) { if (u32(-1)==stage) C=0; } + + adopt_sampler& _texture (LPCSTR texture) { if (C) C->i_Texture (stage,texture); return *this; } + adopt_sampler& _projective (bool _b) { if (C) C->i_Projective(stage,_b); return *this; } + adopt_sampler& _clamp () { if (C) C->i_Address (stage,D3DTADDRESS_CLAMP); return *this; } + adopt_sampler& _wrap () { if (C) C->i_Address (stage,D3DTADDRESS_WRAP); return *this; } + adopt_sampler& _mirror () { if (C) C->i_Address (stage,D3DTADDRESS_MIRROR); return *this; } + adopt_sampler& _f_anisotropic () { if (C) C->i_Filter (stage,D3DTEXF_ANISOTROPIC,D3DTEXF_LINEAR,D3DTEXF_ANISOTROPIC); return *this; } + adopt_sampler& _f_trilinear () { if (C) C->i_Filter (stage,D3DTEXF_LINEAR,D3DTEXF_LINEAR,D3DTEXF_LINEAR); return *this; } + adopt_sampler& _f_bilinear () { if (C) C->i_Filter (stage,D3DTEXF_LINEAR,D3DTEXF_POINT, D3DTEXF_LINEAR); return *this; } + adopt_sampler& _f_linear () { if (C) C->i_Filter (stage,D3DTEXF_LINEAR,D3DTEXF_NONE, D3DTEXF_LINEAR); return *this; } + adopt_sampler& _f_none () { if (C) C->i_Filter (stage,D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_POINT); return *this; } + adopt_sampler& _fmin_none () { if (C) C->i_Filter_Min(stage,D3DTEXF_NONE); return *this; } + adopt_sampler& _fmin_point () { if (C) C->i_Filter_Min(stage,D3DTEXF_POINT); return *this; } + adopt_sampler& _fmin_linear () { if (C) C->i_Filter_Min(stage,D3DTEXF_LINEAR); return *this; } + adopt_sampler& _fmin_aniso () { if (C) C->i_Filter_Min(stage,D3DTEXF_ANISOTROPIC); return *this; } + adopt_sampler& _fmip_none () { if (C) C->i_Filter_Mip(stage,D3DTEXF_NONE); return *this; } + adopt_sampler& _fmip_point () { if (C) C->i_Filter_Mip(stage,D3DTEXF_POINT); return *this; } + adopt_sampler& _fmip_linear () { if (C) C->i_Filter_Mip(stage,D3DTEXF_LINEAR); return *this; } + adopt_sampler& _fmag_none () { if (C) C->i_Filter_Mag(stage,D3DTEXF_NONE); return *this; } + adopt_sampler& _fmag_point () { if (C) C->i_Filter_Mag(stage,D3DTEXF_POINT); return *this; } + adopt_sampler& _fmag_linear () { if (C) C->i_Filter_Mag(stage,D3DTEXF_LINEAR); return *this; } + adopt_sampler& _comp_less () { if (C) C->i_Comparison(stage,GL_LESS); return *this; } +}; + +// wrapper +class adopt_compiler +{ + CBlender_Compile* C; +public: + adopt_compiler (CBlender_Compile* _C) : C(_C) { } + adopt_compiler (const adopt_compiler& _C) : C(_C.C) { } + + adopt_compiler& _options (int P, bool S) { C->SetParams (P,S); return *this; } + adopt_compiler& _o_emissive (bool E) { C->SH->flags.bEmissive=E; return *this; } + adopt_compiler& _o_distort (bool E) { C->SH->flags.bDistort=E; return *this; } + adopt_compiler& _o_wmark (bool E) { C->SH->flags.bWmark=E; return *this; } + adopt_compiler& _pass (LPCSTR vs, LPCSTR ps) { C->r_Pass (vs,ps,true); return *this; } + adopt_compiler& _fog (bool _fog) { C->PassSET_LightFog (FALSE,_fog); return *this; } + adopt_compiler& _ZB (bool _test, bool _write) { C->PassSET_ZB (_test,_write); return *this; } + adopt_compiler& _blend (bool _blend, u32 abSRC, u32 abDST) { C->PassSET_ablend_mode(_blend,abSRC,abDST); return *this; } + adopt_compiler& _aref (bool _aref, u32 aref) { C->PassSET_ablend_aref(_aref,aref); return *this; } + adopt_compiler& _color_write_enable (bool cR, bool cG, bool cB, bool cA) { C->r_ColorWriteEnable(cR, cG, cB, cA); return *this; } + adopt_sampler _sampler (LPCSTR _name) { u32 s = C->r_Sampler(_name,0); return adopt_sampler(C,s); } +}; + +class adopt_blend +{ +public: +}; + +void LuaLog(LPCSTR caMessage) +{ + MDB; + Lua::LuaOut (Lua::eLuaMessageTypeMessage,"%s",caMessage); +} +void LuaError(lua_State* L) +{ + xrDebug::Fatal(DEBUG_INFO,"LUA error: %s",lua_tostring(L,-1)); +} + +#ifndef PURE_ALLOC +# ifndef USE_MEMORY_MONITOR +# define USE_DL_ALLOCATOR +# endif // USE_MEMORY_MONITOR +#endif // PURE_ALLOC + +#ifndef USE_DL_ALLOCATOR + static void *lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize) + { + (void)ud; + (void)osize; + if (nsize == 0) { + xr_free (ptr); + return NULL; + } + +# ifdef DEBUG_MEMORY_NAME + return Memory.mem_realloc (ptr, nsize, "LUA:Render"); +# else // DEBUG_MEMORY_MANAGER + return Memory.mem_realloc (ptr, nsize); +# endif // DEBUG_MEMORY_MANAGER + } +#else // USE_DL_ALLOCATOR +# include "../xrRender/doug_lea_memory_allocator.h" + + static void *lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize) + { + (void)ud; + (void)osize; + if (nsize == 0) { dlfree (ptr); return NULL; } + else return dlrealloc (ptr, nsize); + } +#endif // USE_DL_ALLOCATOR + +// export +void CResourceManager::LS_Load () +{ + LSVM = lua_newstate(lua_alloc, NULL); + if (!LSVM) { + Msg ("! ERROR : Cannot initialize LUA VM!"); + return; + } + + // initialize lua standard library functions + luaopen_base (LSVM); + luaopen_table (LSVM); + luaopen_string (LSVM); + luaopen_math (LSVM); + luaopen_jit (LSVM); + + luabind::open (LSVM); +#if !XRAY_EXCEPTIONS + if (0==luabind::get_error_callback()) + luabind::set_error_callback (LuaError); +#endif + + function (LSVM, "log", LuaLog); + + module (LSVM) + [ + class_("_sampler") + .def( constructor()) + .def("texture", &adopt_sampler::_texture ,return_reference_to(_1)) + .def("project", &adopt_sampler::_projective ,return_reference_to(_1)) + .def("clamp", &adopt_sampler::_clamp ,return_reference_to(_1)) + .def("wrap", &adopt_sampler::_wrap ,return_reference_to(_1)) + .def("mirror", &adopt_sampler::_mirror ,return_reference_to(_1)) + .def("f_anisotropic", &adopt_sampler::_f_anisotropic ,return_reference_to(_1)) + .def("f_trilinear", &adopt_sampler::_f_trilinear ,return_reference_to(_1)) + .def("f_bilinear", &adopt_sampler::_f_bilinear ,return_reference_to(_1)) + .def("f_linear", &adopt_sampler::_f_linear ,return_reference_to(_1)) + .def("f_none", &adopt_sampler::_f_none ,return_reference_to(_1)) + .def("fmin_none", &adopt_sampler::_fmin_none ,return_reference_to(_1)) + .def("fmin_point", &adopt_sampler::_fmin_point ,return_reference_to(_1)) + .def("fmin_linear", &adopt_sampler::_fmin_linear ,return_reference_to(_1)) + .def("fmin_aniso", &adopt_sampler::_fmin_aniso ,return_reference_to(_1)) + .def("fmip_none", &adopt_sampler::_fmip_none ,return_reference_to(_1)) + .def("fmip_point", &adopt_sampler::_fmip_point ,return_reference_to(_1)) + .def("fmip_linear", &adopt_sampler::_fmip_linear ,return_reference_to(_1)) + .def("fmag_none", &adopt_sampler::_fmag_none ,return_reference_to(_1)) + .def("fmag_point", &adopt_sampler::_fmag_point ,return_reference_to(_1)) + .def("fmag_linear", &adopt_sampler::_fmag_linear ,return_reference_to(_1)) + .def("comp_less", &adopt_sampler::_comp_less ,return_reference_to(_1)), + + class_("_compiler") + .def( constructor()) + .def("begin", &adopt_compiler::_pass ,return_reference_to(_1)) + .def("sorting", &adopt_compiler::_options ,return_reference_to(_1)) + .def("emissive", &adopt_compiler::_o_emissive ,return_reference_to(_1)) + .def("distort", &adopt_compiler::_o_distort ,return_reference_to(_1)) + .def("wmark", &adopt_compiler::_o_wmark ,return_reference_to(_1)) + .def("fog", &adopt_compiler::_fog ,return_reference_to(_1)) + .def("zb", &adopt_compiler::_ZB ,return_reference_to(_1)) + .def("blend", &adopt_compiler::_blend ,return_reference_to(_1)) + .def("aref", &adopt_compiler::_aref ,return_reference_to(_1)) + .def("color_write_enable", &adopt_compiler::_color_write_enable,return_reference_to(_1)) + .def("sampler", &adopt_compiler::_sampler ), // returns sampler-object + + class_("blend") + .enum_("blend") + [ + value("zero", int(D3DBLEND_ZERO)), + value("one", int(D3DBLEND_ONE)), + value("srccolor", int(D3DBLEND_SRCCOLOR)), + value("invsrccolor", int(D3DBLEND_INVSRCCOLOR)), + value("srcalpha", int(D3DBLEND_SRCALPHA)), + value("invsrcalpha", int(D3DBLEND_INVSRCALPHA)), + value("destalpha", int(D3DBLEND_DESTALPHA)), + value("invdestalpha", int(D3DBLEND_INVDESTALPHA)), + value("destcolor", int(D3DBLEND_DESTCOLOR)), + value("invdestcolor", int(D3DBLEND_INVDESTCOLOR)), + value("srcalphasat", int(D3DBLEND_SRCALPHASAT)) + ] + ]; + + // load shaders + xr_vector* folder = FS.file_list_open ("$game_shaders$",::Render->getShaderPath(),FS_ListFiles|FS_RootOnly); + VERIFY (folder); + for (u32 it=0; itsize(); it++) { + string_path namesp,fn; + strcpy_s (namesp,(*folder)[it]); + if (0==strext(namesp) || 0!=xr_strcmp(strext(namesp),".s")) continue; + *strext (namesp)=0; + if (0==namesp[0]) strcpy_s (namesp,"_G"); + strconcat (sizeof(fn),fn,::Render->getShaderPath(),(*folder)[it]); + FS.update_path (fn,"$game_shaders$",fn); + try { + Script::bfLoadFileIntoNamespace (LSVM,fn,namesp,true); + } catch (...) + { + Log(lua_tostring(LSVM,-1)); + } + } + FS.file_list_close (folder); +} + +void CResourceManager::LS_Unload () +{ + lua_close (LSVM); + LSVM = NULL; +} + +BOOL CResourceManager::_lua_HasShader (LPCSTR s_shader) +{ + string256 undercorated; + for (int i=0, l=xr_strlen(s_shader)+1; i_GetDetailTexture(*C.L_textures[0],C.detail_texture,C.detail_scaler); + //C.bDetail = glRenderDeviceRender::Instance().Resources->m_textures_description.GetDetailTexture(C.L_textures[0],C.detail_texture,C.detail_scaler); + C.bDetail = glRenderDeviceRender::Instance().Resources->m_textures_description.GetDetailTexture(C.L_textures[0],C.detail_texture,C.detail_scaler); + + if (C.bDetail) S.E[0] = C._lua_Compile(s_shader,"normal_hq"); + else S.E[0] = C._lua_Compile(s_shader,"normal"); + } else { + if (Script::bfIsObjectPresent(LSVM,s_shader,"normal",LUA_TFUNCTION)) + { + C.iElement = 0; +//. C.bDetail = glRenderDeviceRender::Instance().Resources->_GetDetailTexture(*C.L_textures[0],C.detail_texture,C.detail_scaler); + //C.bDetail = glRenderDeviceRender::Instance().Resources->m_textures_description.GetDetailTexture(C.L_textures[0],C.detail_texture,C.detail_scaler); + C.bDetail = glRenderDeviceRender::Instance().Resources->m_textures_description.GetDetailTexture(C.L_textures[0],C.detail_texture,C.detail_scaler); + S.E[0] = C._lua_Compile(s_shader,"normal"); + } + } + + // Compile element (LOD1) + if (Script::bfIsObjectPresent(LSVM,s_shader,"normal",LUA_TFUNCTION)) + { + C.iElement = 1; +//. C.bDetail = glRenderDeviceRender::Instance().Resources->_GetDetailTexture(*C.L_textures[0],C.detail_texture,C.detail_scaler); + //C.bDetail = glRenderDeviceRender::Instance().Resources->m_textures_description.GetDetailTexture(C.L_textures[0],C.detail_texture,C.detail_scaler); + C.bDetail = glRenderDeviceRender::Instance().Resources->m_textures_description.GetDetailTexture(C.L_textures[0],C.detail_texture,C.detail_scaler); + S.E[1] = C._lua_Compile(s_shader,"normal"); + } + + // Compile element + if (Script::bfIsObjectPresent(LSVM,s_shader,"l_point",LUA_TFUNCTION)) + { + C.iElement = 2; + C.bDetail = FALSE; + S.E[2] = C._lua_Compile(s_shader,"l_point");; + } + + // Compile element + if (Script::bfIsObjectPresent(LSVM,s_shader,"l_spot",LUA_TFUNCTION)) + { + C.iElement = 3; + C.bDetail = FALSE; + S.E[3] = C._lua_Compile(s_shader,"l_spot");; + } + + // Compile element + if (Script::bfIsObjectPresent(LSVM,s_shader,"l_special",LUA_TFUNCTION)) + { + C.iElement = 4; + C.bDetail = FALSE; + S.E[4] = C._lua_Compile(s_shader,"l_special"); + } + + // Search equal in shaders array + for (u32 it=0; itdwFlags |= xr_resource_flagged::RF_REGISTERED; + v_shaders.push_back (N); + return N; +} + +ShaderElement* CBlender_Compile::_lua_Compile (LPCSTR namesp, LPCSTR name) +{ + ShaderElement E; + SH = &E; + RS.Invalidate (); + + // Compile + LPCSTR t_0 = *L_textures[0] ? *L_textures[0] : "null"; + LPCSTR t_1 = (L_textures.size() > 1) ? *L_textures[1] : "null"; + LPCSTR t_d = detail_texture ? detail_texture : "null" ; + lua_State* LSVM = glRenderDeviceRender::Instance().Resources->LSVM; + object shader = get_globals(LSVM)[namesp]; + functor element = object_cast >(shader[name]); + adopt_compiler ac = adopt_compiler(this); + element (ac,t_0,t_1,t_d); + r_End (); + ShaderElement* _r = glRenderDeviceRender::Instance().Resources->_CreateElement(E); + return _r; +} diff --git a/src/Layers/xrRenderPC_GL/glStatsRender.cpp b/src/Layers/xrRenderPC_GL/glStatsRender.cpp new file mode 100644 index 00000000000..0d881f6d2dc --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glStatsRender.cpp @@ -0,0 +1,64 @@ +#include "stdafx.h" +#include "glStatsRender.h" +#include "../../xrEngine/GameFont.h" +#include "glRenderDeviceRender.h" + +void glStatsRender::Copy(IStatsRender&_in) +{ + *this = *((glStatsRender*)&_in); +} + +void glStatsRender::OutData1(CGameFont &F) +{ + F.OutNext("VERT: %d/%d", RCache.stat.verts, RCache.stat.calls ? RCache.stat.verts / RCache.stat.calls : 0); + F.OutNext("POLY: %d/%d", RCache.stat.polys, RCache.stat.calls ? RCache.stat.polys / RCache.stat.calls : 0); + F.OutNext("DIP/DP: %d", RCache.stat.calls); +} + +void glStatsRender::OutData2(CGameFont &F) +{ +#ifdef DEBUG + F.OutNext("SH/T/M/C: %d/%d/%d/%d", RCache.stat.states, RCache.stat.textures, RCache.stat.matrices, RCache.stat.constants); + F.OutNext("RT/PS/VS: %d/%d/%d", RCache.stat.target_rt, RCache.stat.ps, RCache.stat.vs); + F.OutNext("DCL/VB/IB: %d/%d/%d", RCache.stat.decl, RCache.stat.vb, RCache.stat.ib); +#endif +} + +void glStatsRender::OutData3(CGameFont &F) +{ + F.OutNext("xforms: %d", RCache.stat.xforms); +} + +void glStatsRender::OutData4(CGameFont &F) +{ + F.OutNext("static: %3.1f/%d", RCache.stat.r.s_static.verts / 1024.f, RCache.stat.r.s_static.dips); + F.OutNext("flora: %3.1f/%d", RCache.stat.r.s_flora.verts / 1024.f, RCache.stat.r.s_flora.dips); + F.OutNext(" flora_lods: %3.1f/%d", RCache.stat.r.s_flora_lods.verts / 1024.f, RCache.stat.r.s_flora_lods.dips); + F.OutNext("dynamic: %3.1f/%d", RCache.stat.r.s_dynamic.verts / 1024.f, RCache.stat.r.s_dynamic.dips); + F.OutNext(" dynamic_sw: %3.1f/%d", RCache.stat.r.s_dynamic_sw.verts / 1024.f, RCache.stat.r.s_dynamic_sw.dips); + F.OutNext(" dynamic_inst:%3.1f/%d", RCache.stat.r.s_dynamic_inst.verts / 1024.f, RCache.stat.r.s_dynamic_inst.dips); + F.OutNext(" dynamic_1B: %3.1f/%d", RCache.stat.r.s_dynamic_1B.verts / 1024.f, RCache.stat.r.s_dynamic_1B.dips); + F.OutNext(" dynamic_2B: %3.1f/%d", RCache.stat.r.s_dynamic_2B.verts / 1024.f, RCache.stat.r.s_dynamic_2B.dips); + F.OutNext(" dynamic_3B: %3.1f/%d", RCache.stat.r.s_dynamic_3B.verts / 1024.f, RCache.stat.r.s_dynamic_3B.dips); + F.OutNext(" dynamic_4B: %3.1f/%d", RCache.stat.r.s_dynamic_4B.verts / 1024.f, RCache.stat.r.s_dynamic_4B.dips); + F.OutNext("details: %3.1f/%d", RCache.stat.r.s_details.verts / 1024.f, RCache.stat.r.s_details.dips); +} + +void glStatsRender::GuardVerts(CGameFont &F) +{ + if (RCache.stat.verts>500000) F.OutNext("Verts > 500k: %d", RCache.stat.verts); +} + +void glStatsRender::GuardDrawCalls(CGameFont &F) +{ + if (RCache.stat.calls>1000) F.OutNext("DIP/DP > 1k: %d", RCache.stat.calls); +} + +void glStatsRender::SetDrawParams(IRenderDeviceRender *pRender) +{ + glRenderDeviceRender *pR = (glRenderDeviceRender*)pRender; + + RCache.set_xform_world(Fidentity); + RCache.set_Shader(pR->m_SelectionShader); + RCache.set_c("tfactor", 1, 1, 1, 1); +} diff --git a/src/Layers/xrRenderPC_GL/glStatsRender.h b/src/Layers/xrRenderPC_GL/glStatsRender.h new file mode 100644 index 00000000000..a4927f9b3d5 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glStatsRender.h @@ -0,0 +1,19 @@ +#pragma once + +#include "..\..\Include\xrRender\StatsRender.h" + +class glStatsRender : + public IStatsRender +{ +public: + virtual void Copy(IStatsRender &_in); + + virtual void OutData1(CGameFont &F); + virtual void OutData2(CGameFont &F); + virtual void OutData3(CGameFont &F); + virtual void OutData4(CGameFont &F); + virtual void GuardVerts(CGameFont &F); + virtual void GuardDrawCalls(CGameFont &F); + virtual void SetDrawParams(IRenderDeviceRender *pRender); +}; + diff --git a/src/Layers/xrRenderPC_GL/glTexture.cpp b/src/Layers/xrRenderPC_GL/glTexture.cpp new file mode 100644 index 00000000000..98ddf4baf43 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glTexture.cpp @@ -0,0 +1,190 @@ +// Texture.cpp: implementation of the CTexture class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" + +#include + +void fix_texture_name(LPSTR fn) +{ + LPSTR _ext = strext(fn); + if (_ext && + (0 == stricmp(_ext, ".tga") || + 0 == stricmp(_ext, ".dds") || + 0 == stricmp(_ext, ".bmp") || + 0 == stricmp(_ext, ".ogm"))) + *_ext = 0; +} + +int get_texture_load_lod(LPCSTR fn) +{ + CInifile::Sect& sect = pSettings->r_section("reduce_lod_texture_list"); + CInifile::SectCIt it_ = sect.Data.begin(); + CInifile::SectCIt it_e_ = sect.Data.end(); + + CInifile::SectCIt it = it_; + CInifile::SectCIt it_e = it_e_; + + for(;it!=it_e;++it) + { + if( strstr(fn, it->first.c_str()) ) + { + if(psTextureLOD<1) + return 0; + else + if(psTextureLOD<3) + return 1; + else + return 2; + } + } + + if(psTextureLOD<2) + return 0; + else + if(psTextureLOD<4) + return 1; + else + return 2; +} + +u32 calc_texture_size(int lod, u32 mip_cnt, u32 orig_size) +{ + if (1 == mip_cnt) + return orig_size; + + int _lod = lod; + float res = float(orig_size); + + while (_lod>0){ + --_lod; + res -= res / 1.333f; + } + return iFloor(res); +} + +GLuint CRender::texture_load(LPCSTR fRName, u32& ret_msize, GLenum& ret_desc) +{ + GLuint pTexture = 0; + string_path fn; + u32 dwWidth, dwHeight; + u32 img_size = 0; + int img_loaded_lod = 0; + gli::gl::format fmt; + u32 mip_cnt = u32(-1); + // validation + R_ASSERT(fRName); + R_ASSERT(fRName[0]); + + // make file name + string_path fname; + strcpy_s(fname,fRName); //. andy if (strext(fname)) *strext(fname)=0; + fix_texture_name (fname); + IReader* S = NULL; + // TODO: OGL: Implement bump mapping. + //if (!FS.exist(fn,"$game_textures$", fname, ".dds") && strstr(fname,"_bump")) goto _BUMP_from_base; + if (FS.exist(fn,"$level$", fname, ".dds")) goto _DDS; + if (FS.exist(fn,"$game_saves$", fname, ".dds")) goto _DDS; + if (FS.exist(fn,"$game_textures$", fname, ".dds")) goto _DDS; + + +#ifdef _EDITOR + ELog.Msg(mtError, "Can't find texture '%s'", fname); + return 0; +#else + + Msg("! Can't find texture '%s'", fname); + R_ASSERT(FS.exist(fn, "$game_textures$", "ed\\ed_not_existing_texture", ".dds")); + goto _DDS; + + // xrDebug::Fatal(DEBUG_INFO,"Can't find texture '%s'",fname); + +#endif + +_DDS: + { + // Load and get header + S = FS.r_open(fn); +#ifdef DEBUG + Msg("* Loaded: %s[%d]b", fn, S->length()); +#endif // DEBUG + img_size = S->length(); + R_ASSERT(S); + gli::texture Texture = gli::load((char*)S->pointer(), img_size); + R_ASSERT(!Texture.empty()); + if (gli::is_target_cube(Texture.target())) goto _DDS_CUBE; + else goto _DDS_2D; + + _DDS_CUBE: + { + gli::gl GL; + mip_cnt = Texture.levels(); + dwWidth = Texture.dimensions().x; + dwHeight = Texture.dimensions().y; + fmt = GL.translate(Texture.format()); + + glGenTextures(1, &pTexture); + glBindTexture(GL_TEXTURE_CUBE_MAP, pTexture); + CHK_GL(glTexStorage2D(GL_TEXTURE_CUBE_MAP, mip_cnt, fmt.Internal, dwWidth, dwHeight)); + + for (size_t face = 0; face < Texture.faces(); face++) + { + for (size_t i = 0; i < mip_cnt; i++) + { + if (gli::is_compressed(Texture.format())) + { + CHK_GL(glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, i, 0, 0, Texture.dimensions(i).x, Texture.dimensions(i).y, + fmt.Internal, Texture.size(i), Texture.data(0, face, i))); + } + else { + CHK_GL(glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, i, 0, 0, Texture.dimensions(i).x, Texture.dimensions(i).y, + fmt.External, fmt.Type, Texture.data(0, face, i))); + } + } + } + FS.r_close(S); + + // OK + ret_msize = calc_texture_size(img_loaded_lod, mip_cnt, img_size); + ret_desc = GL_TEXTURE_CUBE_MAP; + return pTexture; + } + _DDS_2D: + { + // Check for LMAP and compress if needed + strlwr(fn); + + + // Load SYS-MEM-surface, bound to device restrictions + gli::gl GL; + mip_cnt = Texture.levels(); + dwWidth = Texture.dimensions().x; + dwHeight = Texture.dimensions().y; + fmt = GL.translate(Texture.format()); + + glGenTextures(1, &pTexture); + glBindTexture(GL_TEXTURE_2D, pTexture); + CHK_GL(glTexStorage2D(GL_TEXTURE_2D, mip_cnt, fmt.Internal, dwWidth, dwHeight)); + for (size_t i = 0; i < mip_cnt; i++) + { + if (gli::is_compressed(Texture.format())) + { + CHK_GL(glCompressedTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, Texture.dimensions(i).x, Texture.dimensions(i).y, + fmt.Internal, Texture.size(i), Texture.data(0, 0, i))); + } + else { + CHK_GL(glTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, Texture.dimensions(i).x, Texture.dimensions(i).y, + fmt.External, fmt.Type, Texture.data(0, 0, i))); + } + } + FS.r_close(S); + + // OK + img_loaded_lod = get_texture_load_lod(fn); + ret_msize = calc_texture_size(img_loaded_lod, mip_cnt, img_size); + ret_desc = GL_TEXTURE_2D; + return pTexture; + } + } +} diff --git a/src/Layers/xrRenderPC_GL/glThunderboltDescRender.cpp b/src/Layers/xrRenderPC_GL/glThunderboltDescRender.cpp new file mode 100644 index 00000000000..26a1dbc8ae0 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glThunderboltDescRender.cpp @@ -0,0 +1,20 @@ +#include "stdafx.h" +#include "glThunderboltDescRender.h" + +void glThunderboltDescRender::Copy(IThunderboltDescRender&_in) +{ + *this = *((glThunderboltDescRender*)&_in); +} + +void glThunderboltDescRender::CreateModel(LPCSTR m_name) +{ + IReader* F = 0; + F = FS.r_open("$game_meshes$", m_name); R_ASSERT2(F, "Empty 'lightning_model'."); + l_model = ::RImplementation.model_CreateDM(F); + FS.r_close(F); +} + +void glThunderboltDescRender::DestroyModel() +{ + ::RImplementation.model_Delete(l_model); +} diff --git a/src/Layers/xrRenderPC_GL/glThunderboltDescRender.h b/src/Layers/xrRenderPC_GL/glThunderboltDescRender.h new file mode 100644 index 00000000000..bf0fff0b857 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glThunderboltDescRender.h @@ -0,0 +1,19 @@ +#pragma once + +#include "..\..\Include\xrRender\ThunderboltDescRender.h" + +class IRender_DetailModel; + +class glThunderboltDescRender : + public IThunderboltDescRender +{ +public: + virtual void Copy(IThunderboltDescRender &_in); + + virtual void CreateModel(LPCSTR m_name); + virtual void DestroyModel(); + //private: +public: + IRender_DetailModel* l_model; +}; + diff --git a/src/Layers/xrRenderPC_GL/glThunderboltRender.cpp b/src/Layers/xrRenderPC_GL/glThunderboltRender.cpp new file mode 100644 index 00000000000..be697800da5 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glThunderboltRender.cpp @@ -0,0 +1,111 @@ +#include "stdafx.h" +#include "glThunderboltRender.h" + +#include "../../xrEngine/thunderbolt.h" +#include "glThunderboltDescRender.h" +#include "glLensFlareRender.h" + +glThunderboltRender::glThunderboltRender() +{ + // geom + hGeom_model.create(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, RCache.Vertex.Buffer(), RCache.Index.Buffer()); + hGeom_gradient.create(FVF::F_LIT, RCache.Vertex.Buffer(), RCache.QuadIB); +} + +glThunderboltRender::~glThunderboltRender() +{ + hGeom_model.destroy(); + hGeom_gradient.destroy(); +} + +void glThunderboltRender::Copy(IThunderboltRender &_in) +{ + *this = *(glThunderboltRender*)&_in; +} + +void glThunderboltRender::Render(CEffect_Thunderbolt &owner) +{ + VERIFY(owner.current); + + // lightning model + float dv = owner.lightning_phase*0.5f; + dv = (owner.lightning_phase>0.5f) ? Random.randI(2)*0.5f : dv; + + RCache.set_CullMode(CULL_NONE); + u32 v_offset, i_offset; + + glThunderboltDescRender *pThRen = (glThunderboltDescRender*)&*owner.current->m_pRender; + + u32 vCount_Lock = pThRen->l_model->number_vertices; + u32 iCount_Lock = pThRen->l_model->number_indices; + IRender_DetailModel::fvfVertexOut* v_ptr = (IRender_DetailModel::fvfVertexOut*) RCache.Vertex.Lock(vCount_Lock, hGeom_model->vb_stride, v_offset); + u16* i_ptr = RCache.Index.Lock(iCount_Lock, i_offset); + // XForm verts + pThRen->l_model->transfer(owner.current_xform, v_ptr, 0xffffffff, i_ptr, 0, 0.f, dv); + // Flush if needed + RCache.Vertex.Unlock(vCount_Lock, hGeom_model->vb_stride); + RCache.Index.Unlock(iCount_Lock); + RCache.set_xform_world(Fidentity); + RCache.set_Shader(pThRen->l_model->shader); + RCache.set_Geometry(hGeom_model); + RCache.Render(D3DPT_TRIANGLELIST, v_offset, 0, vCount_Lock, i_offset, iCount_Lock / 3); + RCache.set_CullMode(CULL_CCW); + + // gradient + Fvector vecSx, vecSy; + u32 VS_Offset; + FVF::LIT *pv = (FVF::LIT*) RCache.Vertex.Lock(8, hGeom_gradient.stride(), VS_Offset); + // top + { + u32 c_val = iFloor(owner.current->m_GradientTop->fOpacity*owner.lightning_phase*255.f); + u32 c = color_rgba(c_val, c_val, c_val, c_val); + vecSx.mul(Device.vCameraRight, owner.current->m_GradientTop->fRadius.x*owner.lightning_size); + vecSy.mul(Device.vCameraTop, -owner.current->m_GradientTop->fRadius.y*owner.lightning_size); + pv->set(owner.current_xform.c.x + vecSx.x - vecSy.x, owner.current_xform.c.y + vecSx.y - vecSy.y, owner.current_xform.c.z + vecSx.z - vecSy.z, c, 0, 0); pv++; + pv->set(owner.current_xform.c.x + vecSx.x + vecSy.x, owner.current_xform.c.y + vecSx.y + vecSy.y, owner.current_xform.c.z + vecSx.z + vecSy.z, c, 0, 1); pv++; + pv->set(owner.current_xform.c.x - vecSx.x - vecSy.x, owner.current_xform.c.y - vecSx.y - vecSy.y, owner.current_xform.c.z - vecSx.z - vecSy.z, c, 1, 0); pv++; + pv->set(owner.current_xform.c.x - vecSx.x + vecSy.x, owner.current_xform.c.y - vecSx.y + vecSy.y, owner.current_xform.c.z - vecSx.z + vecSy.z, c, 1, 1); pv++; + } + // center + { + u32 c_val = iFloor(owner.current->m_GradientTop->fOpacity*owner.lightning_phase*255.f); + u32 c = color_rgba(c_val, c_val, c_val, c_val); + vecSx.mul(Device.vCameraRight, owner.current->m_GradientCenter->fRadius.x*owner.lightning_size); + vecSy.mul(Device.vCameraTop, -owner.current->m_GradientCenter->fRadius.y*owner.lightning_size); + pv->set(owner.lightning_center.x + vecSx.x - vecSy.x, owner.lightning_center.y + vecSx.y - vecSy.y, owner.lightning_center.z + vecSx.z - vecSy.z, c, 0, 0); pv++; + pv->set(owner.lightning_center.x + vecSx.x + vecSy.x, owner.lightning_center.y + vecSx.y + vecSy.y, owner.lightning_center.z + vecSx.z + vecSy.z, c, 0, 1); pv++; + pv->set(owner.lightning_center.x - vecSx.x - vecSy.x, owner.lightning_center.y - vecSx.y - vecSy.y, owner.lightning_center.z - vecSx.z - vecSy.z, c, 1, 0); pv++; + pv->set(owner.lightning_center.x - vecSx.x + vecSy.x, owner.lightning_center.y - vecSx.y + vecSy.y, owner.lightning_center.z - vecSx.z + vecSy.z, c, 1, 1); pv++; + } + RCache.Vertex.Unlock(8, hGeom_gradient.stride()); + RCache.set_xform_world(Fidentity); + RCache.set_Geometry(hGeom_gradient); + RCache.set_Shader(((glFlareRender*)&*owner.current->m_GradientTop->m_pFlare)->hShader); + +#ifdef USE_DX10 + // Hack. Since lightning gradient uses sun shader override z write settings manually + RCache.set_Z(TRUE); + RCache.set_ZFunc(D3DCMP_LESSEQUAL); +#endif // USE_DX10 + +#ifdef USE_DX10 + // Hack. Since lightning gradient uses sun shader override z write settings manually + RCache.set_Z(TRUE); + RCache.set_ZFunc(D3DCMP_LESSEQUAL); +#endif // USE_DX10 + RCache.Render(D3DPT_TRIANGLELIST, VS_Offset, 0, 4, 0, 2); + RCache.set_Shader(((glFlareRender*)&*owner.current->m_GradientCenter->m_pFlare)->hShader); + +#ifdef USE_DX10 + // Hack. Since lightning gradient uses sun shader override z write settings manually + RCache.set_Z(TRUE); + RCache.set_ZFunc(D3DCMP_LESSEQUAL); +#endif // USE_DX10 + +#ifdef USE_DX10 + // Hack. Since lightning gradient uses sun shader override z write settings manually + RCache.set_Z(TRUE); + RCache.set_ZFunc(D3DCMP_LESSEQUAL); +#endif // USE_DX10 + RCache.Render(D3DPT_TRIANGLELIST, VS_Offset + 4, 0, 4, 0, 2); +} diff --git a/src/Layers/xrRenderPC_GL/glThunderboltRender.h b/src/Layers/xrRenderPC_GL/glThunderboltRender.h new file mode 100644 index 00000000000..22768c6f3ba --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glThunderboltRender.h @@ -0,0 +1,18 @@ +#pragma once + +#include "..\..\Include\xrRender\ThunderboltRender.h" + +class glThunderboltRender : + public IThunderboltRender +{ +public: + glThunderboltRender(); + virtual ~glThunderboltRender(); + + virtual void Copy(IThunderboltRender &_in); + + virtual void Render(CEffect_Thunderbolt &owner); +private: + ref_geom hGeom_model; + ref_geom hGeom_gradient; +}; diff --git a/src/Layers/xrRenderPC_GL/glUIRender.cpp b/src/Layers/xrRenderPC_GL/glUIRender.cpp new file mode 100644 index 00000000000..e10816310a1 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glUIRender.cpp @@ -0,0 +1,279 @@ +#include "stdafx.h" +#include "glUIRender.h" + +#include "glUIShader.h" + +glUIRender UIRenderImpl; + +void glUIRender::CreateUIGeom() +{ + hGeom_TL.create(FVF::F_TL, RCache.Vertex.Buffer(), 0); + hGeom_LIT.create(FVF::F_LIT, RCache.Vertex.Buffer(), 0); +} + +void glUIRender::DestroyUIGeom() +{ + hGeom_TL = NULL; + hGeom_LIT = NULL; +} + +void glUIRender::SetShader(IUIShader &shader) +{ + glUIShader *pShader = (glUIShader*)&shader; + VERIFY(&pShader); + VERIFY(pShader->hShader); + RCache.set_Shader(pShader->hShader); +} + +void glUIRender::SetAlphaRef(int aref) +{ + //CHK_DX(HW.pDevice->SetRenderState(D3DRS_ALPHAREF,aref)); + RCache.set_AlphaRef(aref); +} +/* +void glUIRender::StartTriList(u32 iMaxVerts) +{ +VERIFY(PrimitiveType==ptNone); +m_PointType = pttLIT; +m_iMaxVerts = iMaxVerts; +start_pv = (FVF::LIT*)RCache.Vertex.Lock (m_iMaxVerts,hGeom_fan.stride(),vOffset); +pv = start_pv; +PrimitiveType = ptTriList; +} + +void glUIRender::FlushTriList() +{ +VERIFY(PrimitiveType==ptTriList); +VERIFY(u32(pv-start_pv)<=m_iMaxVerts); + +std::ptrdiff_t p_cnt = (pv-start_pv)/3; +RCache.Vertex.Unlock (u32(pv-start_pv),hGeom_fan.stride()); +RCache.set_Geometry (hGeom_fan); +if (p_cnt!=0)RCache.Render (D3DPT_TRIANGLELIST,vOffset,u32(p_cnt)); + +PrimitiveType = ptNone; +} + +void glUIRender::StartTriFan(u32 iMaxVerts) +{ +VERIFY(PrimitiveType==ptNone); +m_iMaxVerts = iMaxVerts; +start_pv = (FVF::LIT*)RCache.Vertex.Lock (m_iMaxVerts,hGeom_fan.stride(),vOffset); +pv = start_pv; +PrimitiveType = ptTriFan; +m_PointType = pttLIT; + +} + +void glUIRender::FlushTriFan() +{ +VERIFY(PrimitiveType==ptTriFan); +VERIFY(u32(pv-start_pv)<=m_iMaxVerts); + +std::ptrdiff_t p_cnt = pv-start_pv; +RCache.Vertex.Unlock (u32(p_cnt),hGeom_fan.stride()); +RCache.set_Geometry (hGeom_fan); +if (p_cnt>2) RCache.Render (D3DPT_TRIANGLEFAN,vOffset,u32(p_cnt-2)); + +PrimitiveType = ptNone; +} + +void glUIRender::StartTriStrip(u32 iMaxVerts) +{ +VERIFY(PrimitiveType==ptNone); +m_iMaxVerts = iMaxVerts; +start_pv = (FVF::TL*)RCache.Vertex.Lock (m_iMaxVerts,hGeom_fan.stride(),vOffset); +pv = start_pv; +PrimitiveType = ptTriStrip; +} + +void glUIRender::FlushTriStrip() +{ +} + + +void glUIRender::StartLineStrip(u32 iMaxVerts) +{ +VERIFY(PrimitiveType==ptNone); +m_iMaxVerts = iMaxVerts; +start_pv = (FVF::LIT*)RCache.Vertex.Lock (m_iMaxVerts,hGeom_fan.stride(),vOffset); +pv = start_pv; +PrimitiveType = ptLineStrip; +m_PointType = pttLIT; +} + +void glUIRender::FlushLineStrip() +{ +VERIFY(PrimitiveType==ptLineStrip); +VERIFY(u32(pv-start_pv)<=m_iMaxVerts); + +std::ptrdiff_t p_cnt = pv-start_pv; +RCache.Vertex.Unlock (u32(p_cnt),hGeom_fan.stride()); +RCache.set_Geometry (hGeom_fan); +if (p_cnt>1) RCache.Render (D3DPT_LINESTRIP,vOffset,u32(p_cnt-1)); + +PrimitiveType = ptNone; +} + +void glUIRender::StartLineList(u32 iMaxVerts) +{ +VERIFY(PrimitiveType==ptNone); +m_iMaxVerts = iMaxVerts; +start_pv = (FVF::LIT*)RCache.Vertex.Lock (m_iMaxVerts,hGeom_fan.stride(),vOffset); +pv = start_pv; +PrimitiveType = ptLineList; +} + +void glUIRender::FlushLineList() +{ +VERIFY(PrimitiveType==ptLineList); +VERIFY(u32(pv-start_pv)<=m_iMaxVerts); + +std::ptrdiff_t p_cnt = pv-start_pv; +RCache.Vertex.Unlock (u32(p_cnt),hGeom_fan.stride()); +RCache.set_Geometry (hGeom_fan); +if (p_cnt>1) RCache.Render (D3DPT_LINELIST,vOffset,u32(p_cnt)/2); + +PrimitiveType = ptNone; +} +*/ +void glUIRender::SetScissor(Irect* rect) +{ + RCache.set_Scissor(rect); +} + +void glUIRender::GetActiveTextureResolution(Fvector2 &res) +{ + CTexture* T = RCache.get_ActiveTexture(0); + res.set(float(T->get_Width()), float(T->get_Height())); +} + +LPCSTR glUIRender::UpdateShaderName(LPCSTR tex_name, LPCSTR sh_name) +{ + string_path buff; + if (FS.exist(buff, "$game_textures$", tex_name, ".ogm")) + return "hud\\movie"; + else + return sh_name; +} +/* +void glUIRender::PushPoint(float x, float y, u32 c, float u, float v) +{ +VERIFY(m_PointType==pttNone); +pv->set(x, y, 0.0f, c, u, v); +++pv; +} +*/ +/* +void glUIRender::PushPoint(int x, int y, u32 c, float u, float v) +{ +VERIFY(m_PointType==pttNone); +pv->set(x, y, 0, c, u, v); +++pv; +} +*/ + +void glUIRender::PushPoint(float x, float y, float z, u32 C, float u, float v) +{ + //. VERIFY(m_PointType==pttLIT); + switch (m_PointType) + { + case pttLIT: + LIT_pv->set(x, y, z, C, u, v); + ++LIT_pv; + break; + case pttTL: + TL_pv->set(x, y, C, u, v); + ++TL_pv; + break; + } +} + +void glUIRender::StartPrimitive(u32 iMaxVerts, ePrimitiveType primType, ePointType pointType) +{ + VERIFY(PrimitiveType == ptNone); + VERIFY(m_PointType == ptNone); + //. R_ASSERT(pointType==pttLIT); + + m_iMaxVerts = iMaxVerts; + PrimitiveType = primType; + m_PointType = pointType; + + switch (m_PointType) + { + case pttLIT: + LIT_start_pv = (FVF::LIT*)RCache.Vertex.Lock(m_iMaxVerts, hGeom_LIT.stride(), vOffset); + LIT_pv = LIT_start_pv; + break; + case pttTL: + TL_start_pv = (FVF::TL*)RCache.Vertex.Lock(m_iMaxVerts, hGeom_TL.stride(), vOffset); + TL_pv = TL_start_pv; + break; + } +} + +void glUIRender::FlushPrimitive() +{ + u32 primCount = 0; + _D3DPRIMITIVETYPE d3dPrimType = D3DPT_FORCE_DWORD; + std::ptrdiff_t p_cnt = 0; + + switch (m_PointType) + { + case pttLIT: + p_cnt = LIT_pv - LIT_start_pv; + VERIFY(u32(p_cnt) <= m_iMaxVerts); + + RCache.Vertex.Unlock(u32(p_cnt), hGeom_LIT.stride()); + RCache.set_Geometry(hGeom_LIT); + break; + case pttTL: + p_cnt = TL_pv - TL_start_pv; + VERIFY(u32(p_cnt) <= m_iMaxVerts); + + RCache.Vertex.Unlock(u32(p_cnt), hGeom_TL.stride()); + RCache.set_Geometry(hGeom_TL); + break; + default: + NODEFAULT; + } + + // Update data for primitive type + switch (PrimitiveType) + { + case ptTriStrip: + primCount = (u32)(p_cnt - 2); + d3dPrimType = D3DPT_TRIANGLESTRIP; + break; + case ptTriList: + primCount = (u32)(p_cnt / 3); + d3dPrimType = D3DPT_TRIANGLELIST; + break; + case ptLineStrip: + primCount = (u32)(p_cnt - 1); + d3dPrimType = D3DPT_LINESTRIP; + break; + case ptLineList: + primCount = (u32)(p_cnt / 2); + d3dPrimType = D3DPT_LINELIST; + break; + default: + NODEFAULT; + } + + if (primCount>0) + RCache.Render(d3dPrimType, vOffset, primCount); + + PrimitiveType = ptNone; + m_PointType = pttNone; +} + +void glUIRender::CacheSetXformWorld(const Fmatrix& M) +{ + RCache.set_xform_world(M); +} + +void glUIRender::CacheSetCullMode(CullMode m) +{ + RCache.set_CullMode(CULL_NONE + m); +} diff --git a/src/Layers/xrRenderPC_GL/glUIRender.h b/src/Layers/xrRenderPC_GL/glUIRender.h new file mode 100644 index 00000000000..73f59bc5def --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glUIRender.h @@ -0,0 +1,59 @@ +#pragma once + +#include "..\..\Include\xrRender\UIRender.h" + +class glUIRender : + public IUIRender +{ +public: + glUIRender() : PrimitiveType(ptNone), m_PointType(pttNone) { ; } + + virtual void CreateUIGeom(); + virtual void DestroyUIGeom(); + + virtual void SetShader(IUIShader &shader); + virtual void SetAlphaRef(int aref); + //. virtual void StartTriList(u32 iMaxVerts); + //. virtual void FlushTriList(); + //. virtual void StartTriFan(u32 iMaxVerts); + //. virtual void FlushTriFan(); + //virtual void StartTriStrip(u32 iMaxVerts); + //virtual void FlushTriStrip(); + //. virtual void StartLineStrip(u32 iMaxVerts); + //. virtual void FlushLineStrip(); + //. virtual void StartLineList(u32 iMaxVerts); + //. virtual void FlushLineList(); + virtual void SetScissor(Irect* rect = NULL); + virtual void GetActiveTextureResolution(Fvector2 &res); + + //. virtual void PushPoint(float x, float y, u32 c, float u, float v); + // virtual void PushPoint(int x, int y, u32 c, float u, float v); + virtual void PushPoint(float x, float y, float z, u32 C, float u, float v); + + virtual void StartPrimitive(u32 iMaxVerts, ePrimitiveType primType, ePointType pointType); + virtual void FlushPrimitive(); + + virtual LPCSTR UpdateShaderName(LPCSTR tex_name, LPCSTR sh_name); + + virtual void CacheSetXformWorld(const Fmatrix& M); + virtual void CacheSetCullMode(CullMode); + +private: + ref_geom hGeom_TL; + ref_geom hGeom_LIT; + + ePrimitiveType PrimitiveType; + ePointType m_PointType; + + // Vertex buffer attributes + u32 m_iMaxVerts; + u32 vOffset; + + FVF::TL* TL_start_pv; + FVF::TL* TL_pv; + + FVF::LIT* LIT_start_pv; + FVF::LIT* LIT_pv; +}; + +extern glUIRender UIRenderImpl; diff --git a/src/Layers/xrRenderPC_GL/glUISequenceVideoItem.cpp b/src/Layers/xrRenderPC_GL/glUISequenceVideoItem.cpp new file mode 100644 index 00000000000..b545e4f07bb --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glUISequenceVideoItem.cpp @@ -0,0 +1,17 @@ +#include "stdafx.h" +#include "glUISequenceVideoItem.h" + +glUISequenceVideoItem::glUISequenceVideoItem() +{ + m_texture = 0; +} + +void glUISequenceVideoItem::Copy(IUISequenceVideoItem&_in) +{ + *this = *((glUISequenceVideoItem*)&_in); +} + +void glUISequenceVideoItem::CaptureTexture() +{ + m_texture = RCache.get_ActiveTexture(0); +} diff --git a/src/Layers/xrRenderPC_GL/glUISequenceVideoItem.h b/src/Layers/xrRenderPC_GL/glUISequenceVideoItem.h new file mode 100644 index 00000000000..a5a14678402 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glUISequenceVideoItem.h @@ -0,0 +1,22 @@ +#pragma once + +#include "..\..\Include\xrRender\UISequenceVideoItem.h" + +class glUISequenceVideoItem : + public IUISequenceVideoItem +{ +public: + glUISequenceVideoItem(); + + virtual void Copy(IUISequenceVideoItem &_in); + + virtual bool HasTexture() { return !!m_texture; } + virtual void CaptureTexture(); + virtual void ResetTexture() { m_texture = 0; } + virtual BOOL video_IsPlaying() { return m_texture->video_IsPlaying(); } + virtual void video_Sync(u32 _time) { m_texture->video_Sync(_time); } + virtual void video_Play(BOOL looped, u32 _time = 0xFFFFFFFF) { return m_texture->video_Play(looped, _time); } + virtual void video_Stop() { m_texture->video_Stop(); }; +private: + CTexture* m_texture; +}; diff --git a/src/Layers/xrRenderPC_GL/glUIShader.cpp b/src/Layers/xrRenderPC_GL/glUIShader.cpp new file mode 100644 index 00000000000..2bb2b5aae28 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glUIShader.cpp @@ -0,0 +1,17 @@ +#include "stdafx.h" +#include "glUIShader.h" + +void glUIShader::Copy(IUIShader&_in) +{ + *this = *((glUIShader*)&_in); +} + +void glUIShader::create(LPCSTR sh, LPCSTR tex) +{ + hShader.create(sh, tex); +} + +void glUIShader::destroy() +{ + hShader.destroy(); +} diff --git a/src/Layers/xrRenderPC_GL/glUIShader.h b/src/Layers/xrRenderPC_GL/glUIShader.h new file mode 100644 index 00000000000..aed79141991 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glUIShader.h @@ -0,0 +1,19 @@ +#pragma once + +#include "..\..\Include\xrRender\UIShader.h" + +class glUIShader : + public IUIShader +{ + friend class glUIRender; + friend class glWallMarkArray; + friend class CRender; +public: + virtual void Copy(IUIShader &_in); + virtual void create(LPCSTR sh, LPCSTR tex = 0); + virtual bool inited() { return hShader; } + virtual void destroy(); + +private: + ref_shader hShader; +}; diff --git a/src/Layers/xrRenderPC_GL/glWallMarkArray.cpp b/src/Layers/xrRenderPC_GL/glWallMarkArray.cpp new file mode 100644 index 00000000000..9d52438727f --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glWallMarkArray.cpp @@ -0,0 +1,46 @@ +#include "stdafx.h" +#include "glWallMarkArray.h" + +#include "glUIShader.h" + +void glWallMarkArray::Copy(IWallMarkArray &_in) +{ + *this = *(glWallMarkArray*)&_in; +} + +glWallMarkArray::~glWallMarkArray() +{ + for (ShaderIt it = m_CollideMarks.begin(); it != m_CollideMarks.end(); ++it) + it->destroy(); +} + +void glWallMarkArray::AppendMark(LPCSTR s_textures) +{ + ref_shader s; + s.create("effects\\wallmark", s_textures); + m_CollideMarks.push_back(s); +} + +void glWallMarkArray::clear() +{ + return m_CollideMarks.clear(); +} + +bool glWallMarkArray::empty() +{ + return m_CollideMarks.empty(); +} + +wm_shader glWallMarkArray::GenerateWallmark() +{ + wm_shader res; + if (!m_CollideMarks.empty()) + ((glUIShader*)&*res)->hShader = m_CollideMarks[::Random.randI(0, m_CollideMarks.size())]; + return res; +} + +ref_shader* glWallMarkArray::glGenerateWallmark() +{ + return m_CollideMarks.empty() ? NULL : + &m_CollideMarks[::Random.randI(0, m_CollideMarks.size())]; +} diff --git a/src/Layers/xrRenderPC_GL/glWallMarkArray.h b/src/Layers/xrRenderPC_GL/glWallMarkArray.h new file mode 100644 index 00000000000..bca8ec5ca93 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glWallMarkArray.h @@ -0,0 +1,23 @@ +#pragma once + +#include "..\..\Include\xrRender\WallMarkArray.h" + +class glWallMarkArray : + public IWallMarkArray +{ +public: + virtual ~glWallMarkArray(); + virtual void Copy(IWallMarkArray &_in); + + virtual void AppendMark(LPCSTR s_textures); + virtual void clear(); + virtual bool empty(); + virtual wm_shader GenerateWallmark(); + + ref_shader* glGenerateWallmark(); +private: + using ShaderVec = xr_vector; + using ShaderIt = ShaderVec::iterator; + + ShaderVec m_CollideMarks; +}; diff --git a/src/Layers/xrRenderPC_GL/gl_R_render.cpp b/src/Layers/xrRenderPC_GL/gl_R_render.cpp new file mode 100644 index 00000000000..cb0e479537c --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_R_render.cpp @@ -0,0 +1,444 @@ +#include "stdafx.h" +#include "../../xrEngine/igame_persistent.h" +#include "../xrRender/FBasicVisual.h" +#include "../../xrEngine/customhud.h" +#include "../../xrEngine/xr_object.h" + +IC bool pred_sp_sort (ISpatial* _1, ISpatial* _2) +{ + float d1 = _1->spatial.sphere.P.distance_to_sqr (Device.vCameraPosition); + float d2 = _2->spatial.sphere.P.distance_to_sqr (Device.vCameraPosition); + return d1q_frustum + ( + lstRenderables, + ISpatial_DB::O_ORDERED, + STYPE_RENDERABLE + STYPE_LIGHTSOURCE, + ViewBase + ); + + // (almost) Exact sorting order (front-to-back) + std::sort (lstRenderables.begin(),lstRenderables.end(),pred_sp_sort); + + // Determine visibility for dynamic part of scene + set_Object (0); + u32 uID_LTRACK = 0xffffffff; + if (phase==PHASE_NORMAL) { + uLastLTRACK ++; + if (lstRenderables.size()) uID_LTRACK = uLastLTRACK%lstRenderables.size(); + + // update light-vis for current entity / actor + CObject* O = g_pGameLevel->CurrentViewEntity(); + if (O) { + CROS_impl* R = (CROS_impl*) O->ROS(); + if (R) R->update (O); + } + + // update light-vis for selected entity + // track lighting environment + if (lstRenderables.size()) { + IRenderable* renderable = lstRenderables[uID_LTRACK]->dcast_Renderable (); + if (renderable) { + CROS_impl* T = (CROS_impl*)renderable->renderable_ROS (); + if (T) T->update (renderable); + } + } + } + } + + // Traverse sector/portal structure + PortalTraverser.traverse + ( + pLastSector, + ViewBase, + Device.vCameraPosition, + m_ViewProjection, + CPortalTraverser::VQ_HOM + CPortalTraverser::VQ_SSA + CPortalTraverser::VQ_FADE + //. disabled scissoring (HW.Caps.bScissor?CPortalTraverser::VQ_SCISSOR:0) // generate scissoring info + ); + + // Determine visibility for static geometry hierrarhy + for (u32 s_it=0; s_itroot(); + for (u32 v_it=0; v_itr_frustums.size(); v_it++) { + set_Frustum (&(sector->r_frustums[v_it])); + add_Geometry (root); + } + } + + // Traverse frustums + for (u32 o_it=0; o_itspatial_updatesector (); + CSector* sector = (CSector*)spatial->spatial.sector; + if (0==sector) continue; // disassociated from S/P structure + + if (spatial->spatial.type & STYPE_LIGHTSOURCE) { + // lightsource + light* L = (light*) (spatial->dcast_Light()); + VERIFY (L); + float lod = L->get_LOD (); + if (lod>EPS_L) { + vis_data& vis = L->get_homdata ( ); + if (HOM.visible(vis)) Lights.add_light (L); + } + continue ; + } + + if (PortalTraverser.i_marker != sector->r_marker) continue; // inactive (untouched) sector + for (u32 v_it=0; v_itr_frustums.size(); v_it++) { + CFrustum& view = sector->r_frustums[v_it]; + if (!view.testSphere_dirty(spatial->spatial.sphere.P,spatial->spatial.sphere.R)) continue; + + if (spatial->spatial.type & STYPE_RENDERABLE) + { + // renderable + IRenderable* renderable = spatial->dcast_Renderable (); + VERIFY (renderable); + + // Occlusion + // casting is faster then using getVis method + vis_data& v_orig = ((dxRender_Visual*)renderable->renderable.visual)->vis; + vis_data v_copy = v_orig; + v_copy.box.xform (renderable->renderable.xform); + BOOL bVisible = HOM.visible(v_copy); + v_orig.marker = v_copy.marker; + v_orig.accept_frame = v_copy.accept_frame; + v_orig.hom_frame = v_copy.hom_frame; + v_orig.hom_tested = v_copy.hom_tested; + if (!bVisible) break; // exit loop on frustums + + // Rendering + set_Object (renderable); + renderable->renderable_Render (); + set_Object (0); + } + break; // exit loop on frustums + } + } + if (g_pGameLevel && (phase==PHASE_NORMAL)) g_pGameLevel->pHUD->Render_Last(); // HUD + } + else + { + set_Object (0); + if (g_pGameLevel && (phase==PHASE_NORMAL)) g_pGameLevel->pHUD->Render_Last(); // HUD + } +} + +void CRender::render_menu () +{ + // Globals + RCache.set_CullMode (CULL_CCW); + RCache.set_Stencil (FALSE); + RCache.set_ColorWriteEnable (); + + // Main Render + { + Target->u_setrt (Target->rt_Generic_0,0,0,HW.pBaseZB); // LDR RT + g_pGamePersistent->OnRenderPPUI_main() ; // PP-UI + } + // Distort + { + Target->u_setrt (Target->rt_Generic_1,0,0,HW.pBaseZB); // Now RT is a distortion mask + CHK_DX(HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_TARGET, color_rgba(127,127,0,127), 1.0f, 0L)); + g_pGamePersistent->OnRenderPPUI_PP () ; // PP-UI + } + + // Actual Display + RCache.set_FB(0); + RCache.set_Shader ( Target->s_menu ); + RCache.set_Geometry ( Target->g_menu ); + + Fvector2 p0,p1; + u32 Offset; + u32 C = color_rgba (255,255,255,255); + float _w = float(Device.dwWidth); + float _h = float(Device.dwHeight); + float d_Z = EPS_S; + float d_W = 1.f; + p0.set (.5f/_w, .5f/_h); + p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,Target->g_menu->vb_stride,Offset); + pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p0.y); pv++; + pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p1.y); pv++; + pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p0.y); pv++; + pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p1.y); pv++; + RCache.Vertex.Unlock (4,Target->g_menu->vb_stride); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); +} + +extern u32 g_r; +void CRender::Render () +{ + g_r = 1; + VERIFY (0==mapDistort.size()); + + rmNormal(); + + bool _menu_pp = g_pGamePersistent?g_pGamePersistent->OnRenderPPUI_query():false; + if (_menu_pp) { + render_menu () ; + return ; + }; + + IMainMenu* pMainMenu = g_pGamePersistent?g_pGamePersistent->m_pMainMenu:0; + bool bMenu = pMainMenu?pMainMenu->CanSkipSceneRendering():false; + + if( !(g_pGameLevel && g_pGameLevel->pHUD) || bMenu) return; +//. VERIFY (g_pGameLevel && g_pGameLevel->pHUD); + + // Configure + RImplementation.o.distortion = FALSE; // disable distorion + Fcolor sun_color = ((light*)Lights.sun_adapted._get())->color; + BOOL bSUN = ps_r2_ls_flags.test(R2FLAG_SUN) && (u_diffuse2s(sun_color.r,sun_color.g,sun_color.b)>EPS); + if (o.sunstatic) bSUN = FALSE; + // Msg ("sstatic: %s, sun: %s",o.sunstatic?"true":"false", bSUN?"true":"false"); + + // HOM + ViewBase.CreateFromMatrix (Device.mFullTransform, FRUSTUM_P_LRTB + FRUSTUM_P_FAR); + View = 0; + if (!ps_r2_ls_flags.test(R2FLAG_EXP_MT_CALC)) { + HOM.Enable (); + HOM.Render (ViewBase); + } + + //******* Z-prefill calc - DEFERRER RENDERER + if (ps_r2_ls_flags.test(R2FLAG_ZFILL)) { + Device.Statistic->RenderCALC.Begin (); + float z_distance = ps_r2_zfill ; + Fmatrix m_zfill, m_project ; + m_project.build_projection ( + deg2rad(Device.fFOV/* *Device.fASPECT*/), + Device.fASPECT, VIEWPORT_NEAR, + z_distance * g_pGamePersistent->Environment().CurrentEnv->far_plane); + m_zfill.mul (m_project,Device.mView); + r_pmask (true,false); // enable priority "0" + set_Recorder (NULL) ; + phase = PHASE_SMAP; + render_main (m_zfill,false) ; + r_pmask (true,false); // disable priority "1" + Device.Statistic->RenderCALC.End ( ) ; + + // flush + Target->phase_scene_prepare (); + RCache.set_ColorWriteEnable (FALSE); + r_dsgraph_render_graph (0); + RCache.set_ColorWriteEnable ( ); + } else { + Target->phase_scene_prepare (); + } + + //******* + // Sync point + Device.Statistic->RenderDUMP_Wait_S.Begin(); + CHK_GL(q_sync_point[q_sync_count] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)); + CHK_GL(glClientWaitSync(q_sync_point[q_sync_count], GL_SYNC_FLUSH_COMMANDS_BIT, 500)); + CHK_GL(glDeleteSync(q_sync_point[q_sync_count])); + Device.Statistic->RenderDUMP_Wait_S.End (); + q_sync_count = (q_sync_count+1)%HW.Caps.iGPUNum; + + //******* Main calc - DEFERRER RENDERER + // Main calc + Device.Statistic->RenderCALC.Begin (); + r_pmask (true,false,true); // enable priority "0",+ capture wmarks + if (bSUN) set_Recorder (&main_coarse_structure); + else set_Recorder (NULL); + phase = PHASE_NORMAL; + render_main (Device.mFullTransform,true); + set_Recorder (NULL); + r_pmask (true,false); // disable priority "1" + Device.Statistic->RenderCALC.End (); + + BOOL split_the_scene_to_minimize_wait = FALSE; + if (ps_r2_ls_flags.test(R2FLAG_EXP_SPLIT_SCENE)) split_the_scene_to_minimize_wait=TRUE; + + //******* Main render :: PART-0 -- first + if (!split_the_scene_to_minimize_wait) + { + // level, DO NOT SPLIT + Target->phase_scene_begin (); + r_dsgraph_render_hud (); + r_dsgraph_render_graph (0); + r_dsgraph_render_lods (true,true); + if(Details) Details->Render (); + Target->phase_scene_end (); + } else { + // level, SPLIT + Target->phase_scene_begin (); + r_dsgraph_render_graph (0); + Target->disable_aniso (); + } + + //******* Occlusion testing of volume-limited light-sources + Target->phase_occq (); + LP_normal.clear (); + LP_pending.clear (); + { + // perform tests + u32 count = 0; + light_Package& LP = Lights.package; + + // stats + stats.l_shadowed = LP.v_shadowed.size(); + stats.l_unshadowed = LP.v_point.size() + LP.v_spot.size(); + stats.l_total = stats.l_shadowed + stats.l_unshadowed; + + // perform tests + count = _max (count,LP.v_point.size()); + count = _max (count,LP.v_spot.size()); + count = _max (count,LP.v_shadowed.size()); + for (u32 it=0; itvis_prepare (); + if (L->vis.pending) LP_pending.v_point.push_back (L); + else LP_normal.v_point.push_back (L); + } + if (itvis_prepare (); + if (L->vis.pending) LP_pending.v_spot.push_back (L); + else LP_normal.v_spot.push_back (L); + } + if (itvis_prepare (); + if (L->vis.pending) LP_pending.v_shadowed.push_back (L); + else LP_normal.v_shadowed.push_back (L); + } + } + } + LP_normal.sort (); + LP_pending.sort (); + + //******* Main render :: PART-1 (second) + if (split_the_scene_to_minimize_wait) { + // skybox can be drawn here + if (0) + { + Target->u_setrt ( Target->rt_Generic_0, Target->rt_Generic_1,0,HW.pBaseZB ); + RCache.set_CullMode ( CULL_NONE ); + RCache.set_Stencil ( FALSE ); + + // draw skybox + RCache.set_ColorWriteEnable (); + RCache.set_Z (FALSE); + g_pGamePersistent->Environment().RenderSky(); + RCache.set_Z (TRUE); + } + + // level + Target->phase_scene_begin (); + r_dsgraph_render_hud (); + r_dsgraph_render_lods (true,true); + if(Details) Details->Render (); + Target->phase_scene_end (); + } + + if (g_hud && g_hud->RenderActiveItemUIQuery()) + { + Target->phase_wallmarks(); + r_dsgraph_render_hud_ui(); + } + + // Wall marks + if(Wallmarks) { + Target->phase_wallmarks (); + g_r = 0; + Wallmarks->Render (); // wallmarks has priority as normal geometry + } + + // Update incremental shadowmap-visibility solver + { + u32 it=0; + for (it=0; itsvis.flushoccq() ; + } catch (...) + { + Msg ("! Failed to flush-OCCq on light [%d] %X",it,*(u32*)(&Lights_LastFrame[it])); + } + } + Lights_LastFrame.clear (); + } + + // Directional light - fucking sun + if (bSUN) { + RImplementation.stats.l_visible ++; + render_sun_near (); + render_sun (); + render_sun_filtered (); + Target->accum_direct_blend (); + } + + { + Target->phase_accumulator (); + // Render emissive geometry, stencil - write 0x0 at pixel pos + RCache.set_xform_project (Device.mProject); + RCache.set_xform_view (Device.mView); + // Stencil - write 0x1 at pixel pos - + RCache.set_Stencil ( TRUE,D3DCMP_ALWAYS,0x01,0xff,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE,D3DSTENCILOP_KEEP); + //RCache.set_Stencil (TRUE,D3DCMP_ALWAYS,0x00,0xff,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE,D3DSTENCILOP_KEEP); + RCache.set_CullMode (CULL_CCW); + RCache.set_ColorWriteEnable (); + RImplementation.r_dsgraph_render_emissive (); + + // Stencil - draw only where stencil >= 0x1 + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); + RCache.set_CullMode (CULL_NONE); + RCache.set_ColorWriteEnable (); + } + + // Lighting, non dependant on OCCQ + Target->phase_accumulator (); + HOM.Disable (); + render_lights (LP_normal); + + // Lighting, dependant on OCCQ + render_lights (LP_pending); + + // Postprocess + Target->phase_combine (); + VERIFY (0==mapDistort.size()); +} + +void CRender::render_forward () +{ + VERIFY (0==mapDistort.size()); + RImplementation.o.distortion = RImplementation.o.distortion_enabled; // enable distorion + + //******* Main render - second order geometry (the one, that doesn't support deffering) + //.todo: should be done inside "combine" with estimation of of luminance, tone-mapping, etc. + { + // level + r_pmask (false,true); // enable priority "1" + phase = PHASE_NORMAL; + render_main (Device.mFullTransform,false);// + // Igor: we don't want to render old lods on next frame. + mapLOD.clear (); + r_dsgraph_render_graph (1) ; // normal level, secondary priority + PortalTraverser.fade_render () ; // faded-portals + r_dsgraph_render_sorted () ; // strict-sorted geoms + g_pGamePersistent->Environment().RenderLast() ; // rain/thunder-bolts + } + + RImplementation.o.distortion = FALSE; // disable distorion +} diff --git a/src/Layers/xrRenderPC_GL/gl_loader.cpp b/src/Layers/xrRenderPC_GL/gl_loader.cpp new file mode 100644 index 00000000000..a61420a99c2 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_loader.cpp @@ -0,0 +1,389 @@ +#include "stdafx.h" +#include "rgl.h" +#include "../xrRender/ResourceManager.h" +#include "../xrRender/fbasicvisual.h" +#include "../../xrEngine/fmesh.h" +#include "../../xrEngine/xrLevel.h" +#include "../../xrEngine/x_ray.h" +#include "../../xrEngine/IGame_Persistent.h" +#include "../../xrCore/stream_reader.h" + +#include "../xrRenderPC_GL/glRenderDeviceRender.h" + +#include "../xrRenderGL/glBufferUtils.h" + +#include "../xrRender/FHierrarhyVisual.h" + +#pragma warning(push) +#pragma warning(disable:4995) +#include +#pragma warning(pop) + +void CRender::level_Load(IReader* fs) +{ + R_ASSERT (0!=g_pGameLevel); + R_ASSERT (!b_loaded); + + // Begin + pApp->LoadBegin (); + glRenderDeviceRender::Instance().Resources->DeferredLoad (TRUE); + IReader* chunk; + + // Shaders + g_pGamePersistent->LoadTitle ("st_loading_shaders"); + { + chunk = fs->open_chunk (fsL_SHADERS); + R_ASSERT2 (chunk,"Level doesn't builded correctly."); + u32 count = chunk->r_u32 (); + Shaders.resize (count); + for(u32 i=0; ipointer()); + chunk->skip_stringZ (); + if (0==n[0]) continue; + strcpy_s (n_sh,n); + LPSTR delim = strchr(n_sh,'/'); + *delim = 0; + strcpy_s (n_tlist,delim+1); + Shaders[i] = glRenderDeviceRender::Instance().Resources->Create(n_sh,n_tlist); + } + chunk->close(); + } + + // Components + Wallmarks = new CWallmarksEngine(); + Details = new CDetailManager(); + + if (!g_dedicated_server) { + // VB,IB,SWI + g_pGamePersistent->LoadTitle("st_loading_geometry"); + { + CStreamReader *geom = FS.rs_open("$level$","level.geom"); + R_ASSERT2 (geom, "level.geom"); + LoadBuffers (geom,FALSE); + LoadSWIs (geom); + FS.r_close (geom); + } + + //...and alternate/fast geometry + { + CStreamReader *geom = FS.rs_open("$level$","level.geomx"); + R_ASSERT2 (geom, "level.geomX"); + LoadBuffers (geom,TRUE); + FS.r_close (geom); + } + + // Visuals + g_pGamePersistent->LoadTitle("st_loading_spatial_db"); + chunk = fs->open_chunk(fsL_VISUALS); + LoadVisuals (chunk); + chunk->close (); + + // Details + g_pGamePersistent->LoadTitle("st_loading_details"); + Details->Load (); + } + + // Sectors + g_pGamePersistent->LoadTitle("st_loading_sectors_portals"); + LoadSectors (fs); + + // 3D Fluid + // TODO: OGL: Implement 3D Fluid simulation + //Load3DFluid (); + + // HOM + HOM.Load (); + + // Lights + // pApp->LoadTitle ("Loading lights..."); + LoadLights (fs); + + // End + pApp->LoadEnd (); + + // sanity-clear + lstLODs.clear (); + lstLODgroups.clear (); + mapLOD.clear (); + + // signal loaded + b_loaded = TRUE ; +} + +void CRender::level_Unload() +{ + if (0==g_pGameLevel) return; + if (!b_loaded) return; + + u32 I; + + // HOM + HOM.Unload (); + + //*** Details + Details->Unload (); + + //*** Sectors + // 1. + xr_delete (rmPortals); + pLastSector = 0; + vLastCameraPos.set (0,0,0); + // 2. + for (I=0; IRelease(); + xr_delete(Visuals[I]); + } + Visuals.clear (); + + //*** SWI + for (I=0; IEvict (); +// u32 dwUsage = D3DUSAGE_WRITEONLY; + + xr_vector &_DC = _alternative?xDC:nDC; + xr_vector &_VB = _alternative?xVB:nVB; + xr_vector &_IB = _alternative ? xIB : nIB; + + // Vertex buffers + { + // Use DX9-style declarators + CStreamReader *fs = base_fs->open_chunk(fsL_VB); + R_ASSERT2 (fs,"Could not load geometry. File 'level.geom?' corrupted."); + u32 count = fs->r_u32(); + _DC.resize (count); + _VB.resize (count); + for (u32 i=0; ir (dcl,buffer_size); + fs->advance (-(int)buffer_size); + + u32 dcl_len = glBufferUtils::GetDeclLength(dcl)+1; + _DC[i].resize (dcl_len); + fs->r (_DC[i].begin(),dcl_len*sizeof(D3DVERTEXELEMENT9)); + + // count, size + u32 vCount = fs->r_u32 (); + u32 vSize = glBufferUtils::GetDeclVertexSize(dcl); + Msg ("* [Loading VB] %d verts, %d Kb",vCount,(vCount*vSize)/1024); + + // Create and fill + //BYTE* pData = 0; + //R_CHK (HW.pDevice->CreateVertexBuffer(vCount*vSize,dwUsage,0,D3DPOOL_MANAGED,&_VB[i],0)); + //R_CHK (_VB[i]->Lock(0,0,(void**)&pData,0)); +// CopyMemory (pData,fs().pointer(),vCount*vSize); + //fs->r (pData,vCount*vSize); + //_VB[i]->Unlock (); + // TODO: DX10: Check fragmentation. + // Check if buffer is less then 2048 kb + BYTE* pData = xr_alloc(vCount*vSize); + fs->r (pData,vCount*vSize); + glBufferUtils::CreateVertexBuffer(&_VB[i], pData, vCount*vSize); + xr_free(pData); + +// fs->advance (vCount*vSize); + } + fs->close (); + } + + // Index buffers + { + CStreamReader *fs = base_fs->open_chunk(fsL_IB); + u32 count = fs->r_u32(); + _IB.resize (count); + for (u32 i=0; ir_u32 (); + Msg("* [Loading IB] %d indices, %d Kb",iCount,(iCount*2)/1024); + + // Create and fill + //BYTE* pData = 0; + //R_CHK (HW.pDevice->CreateIndexBuffer(iCount*2,dwUsage,D3DFMT_INDEX16,D3DPOOL_MANAGED,&_IB[i],0)); + //R_CHK (_IB[i]->Lock(0,0,(void**)&pData,0)); +// CopyMemory (pData,fs().pointer(),iCount*2); + //fs->r (pData,iCount*2); + //_IB[i]->Unlock (); + + // TODO: DX10: Check fragmentation. + // Check if buffer is less then 2048 kb + BYTE* pData = xr_alloc(iCount*2); + fs->r (pData,iCount*2); + glBufferUtils::CreateIndexBuffer(&_IB[i], pData, iCount * 2); + xr_free(pData); + +// fs().advance (iCount*2); + } + fs->close (); + } +} + +void CRender::LoadVisuals(IReader *fs) +{ + IReader* chunk = 0; + u32 index = 0; + dxRender_Visual* V = 0; + ogf_header H; + + while ((chunk=fs->open_chunk(index))!=0) + { + chunk->r_chunk_safe (OGF_HEADER,&H,sizeof(H)); + V = Models->Instance_Create (H.type); + V->Load(0,chunk,0); + Visuals.push_back(V); + + chunk->close(); + index++; + } +} + +void CRender::LoadLights(IReader *fs) +{ + // lights + Lights.Load (fs); + Lights.LoadHemi(); +} + +struct b_portal +{ + u16 sector_front; + u16 sector_back; + svector vertices; +}; + +void CRender::LoadSectors(IReader* fs) +{ + // allocate memory for portals + u32 size = fs->find_chunk(fsL_PORTALS); + R_ASSERT(0==size%sizeof(b_portal)); + u32 count = size/sizeof(b_portal); + Portals.resize (count); + for (u32 c=0; copen_chunk(fsL_SECTORS); + for (u32 i=0; ; i++) + { + IReader* P = S->open_chunk(i); + if (0==P) break; + + CSector* __S = new CSector(); + __S->load (*P); + Sectors.push_back (__S); + + P->close(); + } + S->close(); + + // load portals + if (count) + { + CDB::Collector CL; + fs->find_chunk (fsL_PORTALS); + for (i=0; ir (&P,sizeof(P)); + CPortal* __P = (CPortal*)Portals[i]; + __P->Setup (P.vertices.begin(),P.vertices.size(), + (CSector*)getSector(P.sector_front), + (CSector*)getSector(P.sector_back)); + for (u32 j=2; jbuild (CL.getV(),int(CL.getVS()),CL.getT(),int(CL.getTS())); + } else { + rmPortals = 0; + } + + // debug + // for (int d=0; dDebugDump (); + + pLastSector = 0; +} + +void CRender::LoadSWIs(CStreamReader* base_fs) +{ + // allocate memory for portals + if (base_fs->find_chunk(fsL_SWIS)){ + CStreamReader *fs = base_fs->open_chunk(fsL_SWIS); + u32 item_count = fs->r_u32(); + + xr_vector::iterator it = SWIs.begin(); + xr_vector::iterator it_e = SWIs.end(); + + for(;it!=it_e;++it) + xr_free( (*it).sw ); + + SWIs.clear_not_free(); + + SWIs.resize (item_count); + for (u32 c=0; cr_u32(); + swi.reserved[1] = fs->r_u32(); + swi.reserved[2] = fs->r_u32(); + swi.reserved[3] = fs->r_u32(); + swi.count = fs->r_u32(); + VERIFY (NULL==swi.sw); + swi.sw = xr_alloc (swi.count); + fs->r (swi.sw,sizeof(FSlideWindow)*swi.count); + } + fs->close (); + } +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget.cpp new file mode 100644 index 00000000000..e0e502422f8 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget.cpp @@ -0,0 +1,748 @@ +#include "stdafx.h" +#include "../xrRender/resourcemanager.h" +#include "blender_light_occq.h" +#include "blender_light_mask.h" +#include "blender_light_direct.h" +#include "blender_light_point.h" +#include "blender_light_spot.h" +#include "blender_light_reflected.h" +#include "blender_combine.h" +#include "blender_bloom_build.h" +#include "blender_luminance.h" +#include "blender_ssao.h" + +#include "glRenderDeviceRender.h" + +void CRenderTarget::u_setrt (const ref_rt& _1, const ref_rt& _2, const ref_rt& _3, GLuint zb) +{ + VERIFY (_1); + dwWidth = _1->dwWidth; + dwHeight = _1->dwHeight; + RCache.set_FB (pFB); + GLuint cnt = 0; + GLenum buffers[3]; + if (_1) + { + buffers[cnt++] = GL_COLOR_ATTACHMENT0; + RCache.set_RT(_1->pSurface, 0); + } + else RCache.set_RT(NULL, 0); + if (_2) + { + buffers[cnt++] = GL_COLOR_ATTACHMENT1; + RCache.set_RT(_2->pSurface, 1); + } + else RCache.set_RT(NULL, 1); + if (_3) + { + buffers[cnt++] = GL_COLOR_ATTACHMENT2; + RCache.set_RT(_3->pSurface, 2); + } + else RCache.set_RT(NULL, 2); + RCache.set_ZB (zb); +// RImplementation.rmNormal (); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + VERIFY(status == GL_FRAMEBUFFER_COMPLETE); + CHK_GL(glDrawBuffers(cnt, buffers)); +} + +void CRenderTarget::u_setrt (const ref_rt& _1, const ref_rt& _2, GLuint zb) +{ + VERIFY (_1); + dwWidth = _1->dwWidth; + dwHeight = _1->dwHeight; + RCache.set_FB (pFB); + GLuint cnt = 0; + GLenum buffers[2]; + if (_1) + { + buffers[cnt++] = GL_COLOR_ATTACHMENT0; + RCache.set_RT(_1->pSurface, 0); + } + else RCache.set_RT(NULL, 0); + if (_2) + { + buffers[cnt++] = GL_COLOR_ATTACHMENT1; + RCache.set_RT(_2->pSurface, 1); + } + else RCache.set_RT(NULL, 1); + RCache.set_ZB (zb); +// RImplementation.rmNormal (); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + VERIFY(status == GL_FRAMEBUFFER_COMPLETE); + CHK_GL(glDrawBuffers(cnt, buffers)); +} + +void CRenderTarget::u_setrt (u32 W, u32 H, GLuint _1, GLuint _2, GLuint _3, GLuint zb) +{ + dwWidth = W; + dwHeight = H; + RCache.set_FB (pFB); + GLuint cnt = 0; + GLenum buffers[3]; + if (_1) buffers[cnt++] = GL_COLOR_ATTACHMENT0; + RCache.set_RT (_1, 0); + if (_2) buffers[cnt++] = GL_COLOR_ATTACHMENT1; + RCache.set_RT (_2, 1); + if (_3) buffers[cnt++] = GL_COLOR_ATTACHMENT2; + RCache.set_RT (_3, 2); + RCache.set_ZB (zb); +// RImplementation.rmNormal (); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + VERIFY(status == GL_FRAMEBUFFER_COMPLETE); + CHK_GL(glDrawBuffers(cnt, buffers)); +} + +void CRenderTarget::u_setbb () +{ + dwWidth = Device.dwWidth; + dwHeight = Device.dwHeight; + RCache.set_FB(); +} + +void CRenderTarget::u_stencil_optimize (BOOL common_stencil) +{ + VERIFY (RImplementation.o.nvstencil); + RCache.set_ColorWriteEnable (FALSE); + u32 Offset; + float _w = float(Device.dwWidth); + float _h = float(Device.dwHeight); + u32 C = color_rgba (255,255,255,255); + float eps = EPS_S; + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); + pv->set (eps, float(_h+eps), eps, 1.f, C, 0, 0); pv++; + pv->set (eps, eps, eps, 1.f, C, 0, 0); pv++; + pv->set (float(_w+eps), float(_h+eps), eps, 1.f, C, 0, 0); pv++; + pv->set (float(_w+eps), eps, eps, 1.f, C, 0, 0); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + RCache.set_CullMode (CULL_NONE ); + if (common_stencil) RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0xff,0x00); // keep/keep/keep + RCache.set_Element (s_occq->E[1] ); + RCache.set_Geometry (g_combine ); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); +} + +// 2D texgen (texture adjustment matrix) +void CRenderTarget::u_compute_texgen_screen (Fmatrix& m_Texgen) +{ + float _w = float(Device.dwWidth); + float _h = float(Device.dwHeight); + float o_w = (.5f / _w); + float o_h = (.5f / _h); + Fmatrix m_TexelAdjust = + { + 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.5f + o_w, 0.5f + o_h, 0.0f, 1.0f + }; + m_Texgen.mul (m_TexelAdjust,RCache.xforms.m_wvp); +} + +// 2D texgen for jitter (texture adjustment matrix) +void CRenderTarget::u_compute_texgen_jitter (Fmatrix& m_Texgen_J) +{ + // place into 0..1 space + Fmatrix m_TexelAdjust = + { + 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.0f, 1.0f + }; + m_Texgen_J.mul (m_TexelAdjust,RCache.xforms.m_wvp); + + // rescale - tile it + float scale_X = float(Device.dwWidth) / float(TEX_jitter); + float scale_Y = float(Device.dwHeight)/ float(TEX_jitter); + float offset = (.5f / float(TEX_jitter)); + m_TexelAdjust.scale (scale_X, scale_Y,1.f ); + m_TexelAdjust.translate_over(offset, offset, 0 ); + m_Texgen_J.mulA_44 (m_TexelAdjust); +} + +u8 fpack (float v) { + s32 _v = iFloor (((v+1)*.5f)*255.f + .5f); + clamp (_v,0,255); + return u8(_v); +} +u8 fpackZ (float v) { + s32 _v = iFloor (_abs(v)*255.f + .5f); + clamp (_v,0,255); + return u8(_v); +} +Fvector vunpack (s32 x, s32 y, s32 z) { + Fvector pck; + pck.x = (float(x)/255.f - .5f)*2.f; + pck.y = (float(y)/255.f - .5f)*2.f; + pck.z = -float(z)/255.f; + return pck; +} +Fvector vunpack (Ivector src) { + return vunpack (src.x,src.y,src.z); +} +Ivector vpack (Fvector src) +{ + Fvector _v; + int bx = fpack (src.x); + int by = fpack (src.y); + int bz = fpackZ(src.z); + // dumb test + float e_best = flt_max; + int r=bx,g=by,b=bz; +#ifdef DEBUG + int d=0; +#else + int d=3; +#endif + for (int x=_max(bx-d,0); x<=_min(bx+d,255); x++) + for (int y=_max(by-d,0); y<=_min(by+d,255); y++) + for (int z=_max(bz-d,0); z<=_min(bz+d,255); z++) + { + _v = vunpack(x,y,z); + float m = _v.magnitude(); + float me = _abs(m-1.f); + if (me>0.03f) continue; + _v.div (m); + float e = _abs(src.dotproduct(_v)-1.f); + if (e samples; + while (samples.size()Evict (); + + // Blenders + b_occq = new CBlender_light_occq(); + b_accum_mask = new CBlender_accum_direct_mask(); + b_accum_direct = new CBlender_accum_direct(); + b_accum_point = new CBlender_accum_point(); + b_accum_spot = new CBlender_accum_spot(); + b_accum_reflected = new CBlender_accum_reflected(); + b_bloom = new CBlender_bloom_build(); + b_ssao = new CBlender_SSAO(); + b_luminance = new CBlender_luminance(); + b_combine = new CBlender_combine(); + + // NORMAL + { + u32 w=Device.dwWidth, h=Device.dwHeight; + rt_Position.create (r2_RT_P, w,h,D3DFMT_A16B16G16R16F); + rt_Normal.create (r2_RT_N, w,h,D3DFMT_A16B16G16R16F); + + // select albedo & accum + if (RImplementation.o.mrtmixdepth) + { + // NV50 + rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A8R8G8B8 ); + rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F); + } + else + { + // can't - mix-depth + if (RImplementation.o.fp16_blend) { + // NV40 + rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A16B16G16R16F); // expand to full + rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F); + } else { + // R4xx, no-fp-blend,-> albedo_wo + VERIFY (RImplementation.o.albedo_wo); + rt_Color.create (r2_RT_albedo, w,h,D3DFMT_A8R8G8B8 ); // normal + rt_Accumulator.create (r2_RT_accum, w,h,D3DFMT_A16B16G16R16F); + rt_Accumulator_temp.create (r2_RT_accum_temp, w,h,D3DFMT_A16B16G16R16F); + } + } + + // generic(LDR) RTs + rt_Generic_0.create (r2_RT_generic0,w,h,D3DFMT_A8R8G8B8 ); + rt_Generic_1.create (r2_RT_generic1,w,h,D3DFMT_A8R8G8B8 ); + // Igor: for volumetric lights + //rt_Generic_2.create (r2_RT_generic2,w,h,D3DFMT_A8R8G8B8 ); + // temp: for higher quality blends + if (RImplementation.o.advancedpp) + rt_Generic_2.create (r2_RT_generic2,w,h,D3DFMT_A16B16G16R16F); + } + + // OCCLUSION + s_occq.create (b_occq, "r2\\occq"); + + // DIRECT (spot) + D3DFORMAT depth_format = (D3DFORMAT)RImplementation.o.HW_smap_FORMAT; + + if (RImplementation.o.HW_smap) + { + D3DFORMAT nullrt = D3DFMT_R5G6B5; + if (RImplementation.o.nullrt) nullrt = (D3DFORMAT)MAKEFOURCC('N','U','L','L'); + + u32 size =RImplementation.o.smapsize ; + rt_smap_depth.create (r2_RT_smap_depth, size,size,depth_format ); + rt_smap_surf.create (r2_RT_smap_surf, size,size,nullrt ); + rt_smap_ZB = NULL; + s_accum_mask.create (b_accum_mask, "r2\\accum_mask"); + s_accum_direct.create (b_accum_direct, "r2\\accum_direct"); + if (RImplementation.o.advancedpp) + s_accum_direct_volumetric.create("accum_volumetric_sun"); + } + else + { + VERIFY(!"Use HW SMAPs only!"); + } + + // POINT + { + s_accum_point.create (b_accum_point, "r2\\accum_point_s"); + accum_point_geom_create (); + g_accum_point.create (D3DFVF_XYZ, g_accum_point_vb, g_accum_point_ib); + accum_omnip_geom_create (); + g_accum_omnipart.create (D3DFVF_XYZ, g_accum_omnip_vb, g_accum_omnip_ib); + } + + // SPOT + { + s_accum_spot.create (b_accum_spot, "r2\\accum_spot_s", "lights\\lights_spot01"); + accum_spot_geom_create (); + g_accum_spot.create (D3DFVF_XYZ, g_accum_spot_vb, g_accum_spot_ib); + } + + { + s_accum_volume.create("accum_volumetric", "lights\\lights_spot01"); + accum_volumetric_geom_create(); + g_accum_volumetric.create( D3DFVF_XYZ, g_accum_volumetric_vb, g_accum_volumetric_ib); + } + + + // REFLECTED + { + s_accum_reflected.create (b_accum_reflected, "r2\\accum_refl"); + } + + // BLOOM + { + D3DFORMAT fmt = D3DFMT_A8R8G8B8; //; // D3DFMT_X8R8G8B8 + u32 w=BLOOM_size_X, h=BLOOM_size_Y; + u32 fvf_build = D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3); + u32 fvf_filter = (u32)D3DFVF_XYZRHW|D3DFVF_TEX8|D3DFVF_TEXCOORDSIZE4(0)|D3DFVF_TEXCOORDSIZE4(1)|D3DFVF_TEXCOORDSIZE4(2)|D3DFVF_TEXCOORDSIZE4(3)|D3DFVF_TEXCOORDSIZE4(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6)|D3DFVF_TEXCOORDSIZE4(7); + rt_Bloom_1.create (r2_RT_bloom1, w,h, fmt); + rt_Bloom_2.create (r2_RT_bloom2, w,h, fmt); + g_bloom_build.create (fvf_build, RCache.Vertex.Buffer(), RCache.QuadIB); + g_bloom_filter.create (fvf_filter, RCache.Vertex.Buffer(), RCache.QuadIB); + s_bloom_dbg_1.create ("effects\\screen_set", r2_RT_bloom1); + s_bloom_dbg_2.create ("effects\\screen_set", r2_RT_bloom2); + s_bloom.create (b_bloom, "r2\\bloom"); + f_bloom_factor = 0.5f; + } + + //HBAO + if (RImplementation.o.ssao_opt_data) + { + u32 w = 0; + u32 h = 0; + if (RImplementation.o.ssao_half_data) + { + w = Device.dwWidth / 2; + h = Device.dwHeight / 2; + } + else + { + w = Device.dwWidth; + h = Device.dwHeight; + } + D3DFORMAT fmt = D3DFMT_R32F; + + rt_half_depth.create (r2_RT_half_depth, w, h, fmt); + s_ssao.create (b_ssao, "r2\\ssao"); + } + + //SSAO + if (RImplementation.o.ssao_blur_on) + { + u32 w = Device.dwWidth, h = Device.dwHeight; + rt_ssao_temp.create (r2_RT_ssao_temp, w, h, D3DFMT_G16R16F); + s_ssao.create (b_ssao, "r2\\ssao"); + } + + // TONEMAP + { + rt_LUM_64.create (r2_RT_luminance_t64, 64, 64, D3DFMT_A16B16G16R16F ); + rt_LUM_8.create (r2_RT_luminance_t8, 8, 8, D3DFMT_A16B16G16R16F ); + s_luminance.create (b_luminance, "r2\\luminance"); + f_luminance_adapt = 0.5f; + + t_LUM_src.create (r2_RT_luminance_src); + t_LUM_dest.create (r2_RT_luminance_cur); + + // create pool + for (u32 it = 0; itClear( 0L, NULL, D3DCLEAR_TARGET, 0x7f7f7f7f, 1.0f, 0L)); + } + RCache.set_FB(0); + } + + // COMBINE + { + s_combine.create (b_combine, "r2\\combine"); + s_combine_volumetric.create ("combine_volumetric"); + s_combine_dbg_0.create ("effects\\screen_set", r2_RT_smap_surf ); + s_combine_dbg_1.create ("effects\\screen_set", r2_RT_luminance_t8 ); + s_combine_dbg_Accumulator.create ("effects\\screen_set", r2_RT_accum ); + g_combine_VP.create (FVF::F_TL, RCache.Vertex.Buffer(), RCache.QuadIB); + g_combine.create (FVF::F_TL, RCache.Vertex.Buffer(), RCache.QuadIB); + g_combine_2UV.create (FVF::F_TL2uv, RCache.Vertex.Buffer(), RCache.QuadIB); + + u32 fvf_aa_blur = D3DFVF_XYZRHW|D3DFVF_TEX4|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3); + g_aa_blur.create (fvf_aa_blur, RCache.Vertex.Buffer(), RCache.QuadIB); + + u32 fvf_aa_AA = D3DFVF_XYZRHW|D3DFVF_TEX7|D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1)|D3DFVF_TEXCOORDSIZE2(2)|D3DFVF_TEXCOORDSIZE2(3)|D3DFVF_TEXCOORDSIZE2(4)|D3DFVF_TEXCOORDSIZE4(5)|D3DFVF_TEXCOORDSIZE4(6); + g_aa_AA.create (fvf_aa_AA, RCache.Vertex.Buffer(), RCache.QuadIB); + + t_envmap_0.create (r2_T_envs0); + t_envmap_1.create (r2_T_envs1); + } + + // Build textures + { + // Build material(s) + { + // Surface + glGenTextures (1, &t_material_surf); + CHK_GL (glBindTexture(GL_TEXTURE_3D, t_material_surf)); + CHK_GL (glTexStorage3D(GL_TEXTURE_3D, 1, GL_RG8, TEX_material_LdotN, TEX_material_LdotH, TEX_material_Count)); + t_material = glRenderDeviceRender::Instance().Resources->_CreateTexture(r2_material); + t_material->surface_set (GL_TEXTURE_3D, t_material_surf); + + // Fill it (addr: x=dot(L,N),y=dot(L,H)) + static const u32 RowPitch = TEX_material_LdotN * 2; + static const u32 SlicePitch = TEX_material_LdotH * RowPitch; + u16 pBits[TEX_material_LdotN*TEX_material_LdotH*TEX_material_Count]; + for (u32 slice=0; slice_CreateTexture (name); + t_noise[it1]->surface_set (GL_TEXTURE_2D, t_noise_surf[it1]); + } + + // Fill it, + static const u32 Pitch = TEX_jitter*sampleSize; + for (u32 y=0; y_CreateTexture (name); + t_noise[it]->surface_set (GL_TEXTURE_2D, t_noise_surf[it]); + + // Fill it, + static const int HBAOPitch = TEX_jitter*sampleSize*sizeof(float); + for (u32 y=0; ysurface_set (GL_TEXTURE_2D, NULL); + +#ifdef DEBUG + //_SHOW_REF ("t_material_surf",t_material_surf); +#endif // DEBUG + glDeleteTextures (1, &t_material_surf); + + t_LUM_src->surface_set (GL_TEXTURE_2D, NULL); + t_LUM_dest->surface_set (GL_TEXTURE_2D, NULL); + +#ifdef DEBUG + GLuint pSurf = 0; + + pSurf = t_envmap_0->surface_get(); + glDeleteTextures(1, &pSurf); + + pSurf = t_envmap_1->surface_get(); + glDeleteTextures(1, &pSurf); + //_SHOW_REF("t_envmap_0 - #small",t_envmap_0->pSurface); + //_SHOW_REF("t_envmap_1 - #small",t_envmap_1->pSurface); +#endif // DEBUG + t_envmap_0->surface_set (GL_TEXTURE_CUBE_MAP, NULL); + t_envmap_1->surface_set (GL_TEXTURE_CUBE_MAP, NULL); + t_envmap_0.destroy (); + t_envmap_1.destroy (); + + // TODO: OGL: Check if we need old style SMAPs +// glDeleteTextures (1, &rt_smap_ZB); + + // Jitter + for (int it=0; itsurface_set (GL_TEXTURE_2D, NULL); + } + glDeleteTextures(TEX_jitter_count, t_noise_surf); + + // + accum_spot_geom_destroy (); + accum_omnip_geom_destroy (); + accum_point_geom_destroy (); + accum_volumetric_geom_destroy(); + + // Blenders + xr_delete (b_combine ); + xr_delete (b_luminance ); + xr_delete (b_bloom ); + xr_delete (b_ssao ); + xr_delete (b_accum_reflected ); + xr_delete (b_accum_spot ); + xr_delete (b_accum_point ); + xr_delete (b_accum_direct ); + xr_delete (b_accum_mask ); + xr_delete (b_occq ); + + glDeleteFramebuffers(1, &pFB); +} + +void CRenderTarget::reset_light_marker( bool bResetStencil) +{ + dwLightMarkerID = 5; + if (bResetStencil) + { + RCache.set_ColorWriteEnable (FALSE); + u32 Offset; + float _w = float(Device.dwWidth); + float _h = float(Device.dwHeight); + u32 C = color_rgba (255,255,255,255); + float eps = EPS_S; + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); + pv->set (eps, float(_h+eps), eps, 1.f, C, 0, 0); pv++; + pv->set (eps, eps, eps, 1.f, C, 0, 0); pv++; + pv->set (float(_w+eps), float(_h+eps), eps, 1.f, C, 0, 0); pv++; + pv->set (float(_w+eps), eps, eps, 1.f, C, 0, 0); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + RCache.set_CullMode (CULL_NONE ); + // Clear everything except last bit + RCache.set_Stencil (TRUE,D3DCMP_ALWAYS,dwLightMarkerID,0x00,0xFE, D3DSTENCILOP_ZERO, D3DSTENCILOP_ZERO, D3DSTENCILOP_ZERO); + //RCache.set_Stencil (TRUE,D3DCMP_ALWAYS,dwLightMarkerID,0x00,0xFF, D3DSTENCILOP_ZERO, D3DSTENCILOP_ZERO, D3DSTENCILOP_ZERO); + RCache.set_Element (s_occq->E[1] ); + RCache.set_Geometry (g_combine ); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + +/* + u32 Offset; + float _w = float(Device.dwWidth); + float _h = float(Device.dwHeight); + u32 C = color_rgba (255,255,255,255); + float eps = 0; + float _dw = 0.5f; + float _dh = 0.5f; + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); + pv->set (-_dw, _h-_dh, eps, 1.f, C, 0, 0); pv++; + pv->set (-_dw, -_dh, eps, 1.f, C, 0, 0); pv++; + pv->set (_w-_dw, _h-_dh, eps, 1.f, C, 0, 0); pv++; + pv->set (_w-_dw, -_dh, eps, 1.f, C, 0, 0); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + RCache.set_Element (s_occq->E[2] ); + RCache.set_Geometry (g_combine ); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); +*/ + } +} + +void CRenderTarget::increment_light_marker() +{ + dwLightMarkerID += 2; + + //if (dwLightMarkerID>10) + if (dwLightMarkerID>255) + reset_light_marker(true); +} + +bool CRenderTarget::need_to_render_sunshafts() +{ + if ( ! (RImplementation.o.advancedpp && ps_r_sun_shafts) ) + return false; + + { + CEnvDescriptor& E = *g_pGamePersistent->Environment().CurrentEnv; + float fValue = E.m_fSunShaftsIntensity; + // TODO: add multiplication by sun color here + if (fValue<0.0001) return false; + } + + return true; +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget.h b/src/Layers/xrRenderPC_GL/gl_rendertarget.h new file mode 100644 index 00000000000..674d87aea9d --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget.h @@ -0,0 +1,269 @@ +#pragma once + +class light; + +//#define DU_SPHERE_NUMVERTEX 92 +//#define DU_SPHERE_NUMFACES 180 +//#define DU_CONE_NUMVERTEX 18 +//#define DU_CONE_NUMFACES 32 +// no less than 2 +#define VOLUMETRIC_SLICES 100 + +class CRenderTarget : public IRender_Target +{ +private: + u32 dwWidth; + u32 dwHeight; + u32 dwAccumulatorClearMark; +public: + enum eStencilOptimizeMode + { + SO_Light = 0, // Default + SO_Combine, // Default + }; + + u32 dwLightMarkerID; + // + IBlender* b_occq; + IBlender* b_accum_mask; + IBlender* b_accum_direct; + IBlender* b_accum_point; + IBlender* b_accum_spot; + IBlender* b_accum_reflected; + IBlender* b_bloom; + IBlender* b_ssao; + IBlender* b_luminance; + IBlender* b_combine; +#ifdef DEBUG + struct dbg_line_t { + Fvector P0,P1; + u32 color; + }; + xr_vector > dbg_spheres; + xr_vector dbg_lines; + xr_vector dbg_planes; +#endif + + // MRT-path + ref_rt rt_Depth; // Z-buffer like - initial depth + ref_rt rt_Position; // 64bit, fat (x,y,z,?) (eye-space) + ref_rt rt_Normal; // 64bit, fat (x,y,z,hemi) (eye-space) + ref_rt rt_Color; // 64/32bit,fat (r,g,b,specular-gloss) (or decompressed MET-8-8-8-8) + + // + ref_rt rt_Accumulator; // 64bit (r,g,b,specular) + ref_rt rt_Accumulator_temp;// only for HW which doesn't feature fp16 blend + ref_rt rt_Generic_0; // 32bit (r,g,b,a) // post-process, intermidiate results, etc. + ref_rt rt_Generic_1; // 32bit (r,g,b,a) // post-process, intermidiate results, etc. + // Igor: for volumetric lights + ref_rt rt_Generic_2; // 32bit (r,g,b,a) // post-process, intermidiate results, etc. + ref_rt rt_Bloom_1; // 32bit, dim/4 (r,g,b,?) + ref_rt rt_Bloom_2; // 32bit, dim/4 (r,g,b,?) + ref_rt rt_LUM_64; // 64bit, 64x64, log-average in all components + ref_rt rt_LUM_8; // 64bit, 8x8, log-average in all components + + // Igor: for async screenshots + GLuint pFB; //32bit (r,g,b,a) is situated in the system memory + + ref_rt rt_LUM_pool [2] ; // 1xfp32,1x1, exp-result -> scaler + ref_texture t_LUM_src ; // source + ref_texture t_LUM_dest ; // destination & usage for current frame + + // env + ref_texture t_envmap_0 ; // env-0 + ref_texture t_envmap_1 ; // env-1 + + // smap + ref_rt rt_smap_surf; // 32bit, color + ref_rt rt_smap_depth; // 24(32) bit, depth + GLuint rt_smap_ZB; // + + // Textures + GLuint t_material_surf; + ref_texture t_material; + + GLuint t_noise_surf[TEX_jitter_count]; + ref_texture t_noise [TEX_jitter_count]; +private: + // OCCq + ref_shader s_occq; + + // Accum + ref_shader s_accum_mask ; + ref_shader s_accum_direct ; + ref_shader s_accum_direct_volumetric; + ref_shader s_accum_point ; + ref_shader s_accum_spot ; + ref_shader s_accum_reflected; + ref_shader s_accum_volume; + + ref_geom g_accum_point ; + ref_geom g_accum_spot ; + ref_geom g_accum_omnipart; + ref_geom g_accum_volumetric; + + GLuint g_accum_point_vb; + GLuint g_accum_point_ib; + + GLuint g_accum_omnip_vb; + GLuint g_accum_omnip_ib; + + GLuint g_accum_spot_vb; + GLuint g_accum_spot_ib; + + GLuint g_accum_volumetric_vb; + GLuint g_accum_volumetric_ib; + + //SSAO + ref_shader s_ssao; + ref_rt rt_ssao_temp; + ref_rt rt_half_depth; + + // Bloom + ref_geom g_bloom_build; + ref_geom g_bloom_filter; + ref_shader s_bloom_dbg_1; + ref_shader s_bloom_dbg_2; + ref_shader s_bloom; + float f_bloom_factor; + + // Luminance + ref_shader s_luminance; + float f_luminance_adapt; + + // Combine + ref_geom g_combine; + ref_geom g_combine_VP; // xy=p,zw=tc + ref_geom g_combine_2UV; + ref_geom g_aa_blur; + ref_geom g_aa_AA; + ref_shader s_combine_dbg_0; + ref_shader s_combine_dbg_1; + ref_shader s_combine_dbg_Accumulator; + ref_shader s_combine; + ref_shader s_combine_volumetric; +public: + ref_shader s_postprocess; + ref_geom g_postprocess; + ref_shader s_menu; + ref_geom g_menu; +private: + float im_noise_time; + u32 im_noise_shift_w; + u32 im_noise_shift_h; + + float param_blur; + float param_gray; + float param_duality_h; + float param_duality_v; + float param_noise; + float param_noise_scale; + float param_noise_fps; + u32 param_color_base; + u32 param_color_gray; + Fvector param_color_add; + + // Igor: used for volumetric lights + bool m_bHasActiveVolumetric; +public: + CRenderTarget (); + ~CRenderTarget (); + void accum_point_geom_create (); + void accum_point_geom_destroy(); + void accum_omnip_geom_create (); + void accum_omnip_geom_destroy(); + void accum_spot_geom_create (); + void accum_spot_geom_destroy (); + // Igor: used for volumetric lights + void accum_volumetric_geom_create(); + void accum_volumetric_geom_destroy(); + + void u_stencil_optimize (BOOL common_stencil=TRUE); + void u_compute_texgen_screen (Fmatrix& dest); + void u_compute_texgen_jitter (Fmatrix& dest); + void u_setrt (const ref_rt& _1, const ref_rt& _2, const ref_rt& _3, GLuint zb); + void u_setrt (const ref_rt& _1, const ref_rt& _2, GLuint zb); + void u_setrt (u32 W, u32 H, GLuint _1, GLuint _2, GLuint _3, GLuint zb); + void u_setbb (); + void u_calc_tc_noise (Fvector2& p0, Fvector2& p1); + void u_calc_tc_duality_ss (Fvector2& r0, Fvector2& r1, Fvector2& l0, Fvector2& l1); + BOOL u_need_PP (); + BOOL u_DBT_enable (float zMin, float zMax); + void u_DBT_disable (); + + void phase_ssao (); + void phase_downsamp (); + void phase_scene_prepare (); + void phase_scene_begin (); + void phase_scene_end (); + void phase_occq (); + void phase_wallmarks (); + void phase_smap_direct (light* L, u32 sub_phase); + void phase_smap_direct_tsh (light* L, u32 sub_phase); + void phase_smap_spot_clear (); + void phase_smap_spot (light* L); + void phase_smap_spot_tsh (light* L); + void phase_accumulator (); + void phase_vol_accumulator (); + void shadow_direct (light* L, u32 dls_phase) { VERIFY(!"CRender::shadow_direct not implemented."); }; + + bool need_to_render_sunshafts(); + + BOOL enable_scissor (light* L); // true if intersects near plane + void enable_dbt_bounds (light* L); + + void disable_aniso (); + + void draw_volume (light* L); + void accum_direct (u32 sub_phase); + void accum_direct_f (u32 sub_phase); + void accum_direct_lum (); + void accum_direct_blend (); + void accum_direct_volumetric (u32 sub_phase, const u32 Offset, const Fmatrix &mShadow); + void accum_point (light* L); + void accum_spot (light* L); + void accum_reflected (light* L); + // Igor: for volumetric lights + void accum_volumetric (light* L); + void phase_bloom (); + void phase_luminance (); + void phase_combine (); + void phase_combine_volumetric(); + void phase_pp (); + + virtual void set_blur (float f) { param_blur=f; } + virtual void set_gray (float f) { param_gray=f; } + virtual void set_duality_h (float f) { param_duality_h=_abs(f); } + virtual void set_duality_v (float f) { param_duality_v=_abs(f); } + virtual void set_noise (float f) { param_noise=f; } + virtual void set_noise_scale (float f) { param_noise_scale=f; } + virtual void set_noise_fps (float f) { param_noise_fps=_abs(f)+EPS_S; } + virtual void set_color_base (u32 f) { param_color_base=f; } + virtual void set_color_gray (u32 f) { param_color_gray=f; } + virtual void set_color_add (const Fvector &f) { param_color_add=f; } + + virtual u32 get_width () { return dwWidth; } + virtual u32 get_height () { return dwHeight; } + + // Need to reset stencil only when marker overflows. + // Don't clear when render for the first time + void reset_light_marker( bool bResetStencil = false); + void increment_light_marker(); + + void DoAsyncScreenshot (); + +#ifdef DEBUG + IC void dbg_addline (Fvector& P0, Fvector& P1, u32 c) { + dbg_lines.push_back (dbg_line_t()); + dbg_lines.back().P0 = P0; + dbg_lines.back().P1 = P1; + dbg_lines.back().color = c; + } + IC void dbg_addplane (Fplane& P0, u32 c) { + dbg_planes.push_back(P0); + } +#else + IC void dbg_addline (Fvector& P0, Fvector& P1, u32 c) {} + IC void dbg_addplane (Fplane& P0, u32 c) {} +#endif +}; diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_direct.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_direct.cpp new file mode 100644 index 00000000000..268780c54d5 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_direct.cpp @@ -0,0 +1,578 @@ +#include "stdafx.h" +#include "../../xrEngine/igame_persistent.h" +#include "../../xrEngine/environment.h" + +void CRenderTarget::accum_direct (u32 sub_phase) +{ + // Choose normal code-path or filtered + phase_accumulator (); + if (RImplementation.o.sunfilter) { + accum_direct_f (sub_phase); + return ; + } + + // TODO: DX10: Remove half pixe offset + // *** assume accumulator setted up *** + light* fuckingsun = (light*)RImplementation.Lights.sun_adapted._get() ; + + // Common calc for quad-rendering + u32 Offset; + u32 C = color_rgba (255,255,255,255); + float _w = float (Device.dwWidth); + float _h = float (Device.dwHeight); + Fvector2 p0,p1; + p0.set (.5f/_w, .5f/_h); + p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + float d_Z = EPS_S, d_W = 1.f; + + // Common constants (light-related) + Fvector L_dir,L_clr; float L_spec; + L_clr.set (fuckingsun->color.r,fuckingsun->color.g,fuckingsun->color.b); + L_spec = u_diffuse2s (L_clr); + Device.mView.transform_dir (L_dir,fuckingsun->direction); + L_dir.normalize (); + + // Perform masking (only once - on the first/near phase) + RCache.set_CullMode (CULL_NONE ); + if (SE_SUN_NEAR==sub_phase) //. + //if( 0 ) + { + // Fill vertex buffer + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); + pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p0.y); pv++; + pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p1.y); pv++; + pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p0.y); pv++; + pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p1.y); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + RCache.set_Geometry (g_combine); + + // setup + float intensity = 0.3f*fuckingsun->color.r + 0.48f*fuckingsun->color.g + 0.22f*fuckingsun->color.b; + Fvector dir = L_dir; + dir.normalize().mul (- _sqrt(intensity+EPS)); + RCache.set_Element (s_accum_mask->E[SE_MASK_DIRECT]); // masker + RCache.set_c ("Ldynamic_dir", dir.x,dir.y,dir.z,0 ); + + // if (stencil>=1 && aref_pass) stencil = light_id + RCache.set_ColorWriteEnable (FALSE ); + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0x01,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE,D3DSTENCILOP_KEEP); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + + // recalculate d_Z, to perform depth-clipping + Fvector center_pt; center_pt.mad (Device.vCameraPosition,Device.vCameraDirection,ps_r2_sun_near); + Device.mFullTransform.transform(center_pt) ; + d_Z = center_pt.z ; + + // nv-stencil recompression + if (RImplementation.o.nvstencil && (SE_SUN_NEAR==sub_phase)) u_stencil_optimize(); //. driver bug? + + // Perform lighting + { + phase_accumulator () ; + RCache.set_CullMode (CULL_NONE); + RCache.set_ColorWriteEnable () ; + + // texture adjustment matrix + //float fTexelOffs = (.5f / float(RImplementation.o.smapsize)); + //float fRange = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_scale:ps_r2_sun_depth_far_scale; + //float fBias = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_bias:ps_r2_sun_depth_far_bias; + //Fmatrix m_TexelAdjust = + //{ + // 0.5f, 0.0f, 0.0f, 0.0f, + // 0.0f, 0.5f, 0.0f, 0.0f, + // 0.0f, 0.0f, fRange, 0.0f, + // 0.5f + fTexelOffs, 0.5f + fTexelOffs, fBias, 1.0f + //}; + float fRange = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_scale:ps_r2_sun_depth_far_scale; + //float fBias = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_bias:ps_r2_sun_depth_far_bias; + // TODO: DX10: Remove this when fix inverse culling for far region + float fBias = (SE_SUN_NEAR==sub_phase)?(-ps_r2_sun_depth_near_bias):ps_r2_sun_depth_far_bias; + Fmatrix m_TexelAdjust = + { + 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f * fRange, 0.0f, + 0.5f, 0.5f, 0.5f + fBias, 1.0f + }; + + // compute xforms + FPU::m64r (); + Fmatrix xf_invview; xf_invview.invert (Device.mView) ; + + // shadow xform + Fmatrix m_shadow; + { + Fmatrix xf_project; xf_project.mul (m_TexelAdjust,fuckingsun->X.D.combine); + m_shadow.mul (xf_project, xf_invview); + + // tsm-bias + if ( (SE_SUN_FAR == sub_phase) && (RImplementation.o.HW_smap) ) + { + Fvector bias; bias.mul (L_dir,ps_r2_sun_tsm_bias); + Fmatrix bias_t; bias_t.translate(bias); + m_shadow.mulB_44 (bias_t); + } + FPU::m24r (); + } + + // clouds xform + Fmatrix m_clouds_shadow; + { + static float w_shift = 0; + Fmatrix m_xform; + Fvector direction = fuckingsun->direction ; + float w_dir = g_pGamePersistent->Environment().CurrentEnv->wind_direction ; + //float w_speed = g_pGamePersistent->Environment().CurrentEnv->wind_velocity ; + Fvector normal ; normal.setHP(w_dir,0); + w_shift += 0.003f*Device.fTimeDelta; + Fvector position; position.set(0,0,0); + m_xform.build_camera_dir (position,direction,normal) ; + Fvector localnormal;m_xform.transform_dir(localnormal,normal); localnormal.normalize(); + m_clouds_shadow.mul (m_xform,xf_invview) ; + m_xform.scale (0.002f,0.002f,1.f) ; + m_clouds_shadow.mulA_44 (m_xform) ; + m_xform.translate (localnormal.mul(w_shift)) ; + m_clouds_shadow.mulA_44 (m_xform) ; + } + + // Make jitter texture + Fvector2 j0,j1; + float scale_X = float(Device.dwWidth) / float(TEX_jitter); + //float scale_Y = float(Device.dwHeight)/ float(TEX_jitter); + float offset = (.5f / float(TEX_jitter)); + j0.set (offset,offset); + j1.set (scale_X,scale_X).add(offset); + + // Fill vertex buffer + FVF::TL2uv* pv = (FVF::TL2uv*) RCache.Vertex.Lock (4,g_combine_2UV->vb_stride,Offset); + //pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p1.y, j0.x, j1.y); pv++; + //pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p0.y, j0.x, j0.y); pv++; + //pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p1.y, j1.x, j1.y); pv++; + //pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p0.y, j1.x, j0.y); pv++; + pv->set (-1, -1, d_Z, d_W, C, 0, 0, 0, 0); pv++; + pv->set (-1, 1, d_Z, d_W, C, 0, 1, 0, scale_X); pv++; + pv->set (1, -1, d_Z, d_W, C, 1, 0, scale_X, 0); pv++; + pv->set (1, 1, d_Z, d_W, C, 1, 1, scale_X, scale_X); pv++; + RCache.Vertex.Unlock (4,g_combine_2UV->vb_stride); + RCache.set_Geometry (g_combine_2UV); + + // setup + RCache.set_Element (s_accum_direct->E[sub_phase]); + RCache.set_c ("Ldynamic_dir", L_dir.x,L_dir.y,L_dir.z,0 ); + RCache.set_c ("Ldynamic_color", L_clr.x,L_clr.y,L_clr.z,L_spec ); + RCache.set_c ("m_shadow", m_shadow ); + RCache.set_c ("m_sunmask", m_clouds_shadow ); + + // nv-DBT + float zMin,zMax; + if (SE_SUN_NEAR==sub_phase) { + zMin = 0; + zMax = ps_r2_sun_near; + } else { + extern float OLES_SUN_LIMIT_27_01_07; + zMin = ps_r2_sun_near; + zMax = OLES_SUN_LIMIT_27_01_07; + } + center_pt.mad(Device.vCameraPosition,Device.vCameraDirection,zMin); Device.mFullTransform.transform (center_pt); + zMin = center_pt.z ; + + center_pt.mad(Device.vCameraPosition,Device.vCameraDirection,zMax); Device.mFullTransform.transform (center_pt); + zMax = center_pt.z ; + +// TODO: DX10: Check if DX10 has analog for NV DBT +// if (u_DBT_enable(zMin,zMax)) { + // z-test always +// HW.pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); +// HW.pDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); +// } + + // Fetch4 : enable +// if (RImplementation.o.HW_smap_FETCH4) { + //. we hacked the shader to force smap on S0 +//# define FOURCC_GET4 MAKEFOURCC('G','E','T','4') +// HW.pDevice->SetSamplerState ( 0, D3DSAMP_MIPMAPLODBIAS, FOURCC_GET4 ); +// } + + // setup stencil + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0xff,0x00); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + + // Fetch4 : disable +// if (RImplementation.o.HW_smap_FETCH4) { + //. we hacked the shader to force smap on S0 +//# define FOURCC_GET1 MAKEFOURCC('G','E','T','1') +// HW.pDevice->SetSamplerState ( 0, D3DSAMP_MIPMAPLODBIAS, FOURCC_GET1 ); +// } + +// TODO: DX10: Check if DX10 has analog for NV DBT + // disable depth bounds +// u_DBT_disable (); + + // Igor: draw volumetric here + //if (ps_r2_ls_flags.test(R2FLAG_SUN_SHAFTS)) + if ( RImplementation.o.advancedpp&&(ps_r_sun_shafts>0)) + accum_direct_volumetric (sub_phase, Offset, m_shadow); + } +} + +void CRenderTarget::accum_direct_blend () +{ + // blend-copy + if (!RImplementation.o.fp16_blend) { + VERIFY(0); + u_setrt (rt_Accumulator,NULL,NULL,HW.pBaseZB); + + // TODO: DX10: remove half pixel offset + // Common calc for quad-rendering + u32 Offset; + u32 C = color_rgba (255,255,255,255); + float _w = float (Device.dwWidth); + float _h = float (Device.dwHeight); + Fvector2 p0,p1; + p0.set (.5f/_w, .5f/_h); + p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + float d_Z = EPS_S, d_W = 1.f; + + // Fill vertex buffer + FVF::TL2uv* pv = (FVF::TL2uv*) RCache.Vertex.Lock (4,g_combine_2UV->vb_stride,Offset); + //pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p1.y, p0.x, p1.y); pv++; + //pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p0.y, p0.x, p0.y); pv++; + //pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p1.y, p1.x, p1.y); pv++; + //pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p0.y, p1.x, p0.y); pv++; + pv->set (-1, -1, d_Z, d_W, C, 0, 0, 0, 0); pv++; + pv->set (-1, 1, d_Z, d_W, C, 0, 1, 0, 1); pv++; + pv->set (1, -1, d_Z, d_W, C, 1, 0, 1, 0); pv++; + pv->set (1, 1, d_Z, d_W, C, 1, 1, 1, 1); pv++; + RCache.Vertex.Unlock (4,g_combine_2UV->vb_stride); + RCache.set_Geometry (g_combine_2UV); + RCache.set_Element (s_accum_mask->E[SE_MASK_ACCUM_2D] ); + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0xff,0x00); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2 ); + } + //dwLightMarkerID += 2; + increment_light_marker(); +} + +void CRenderTarget::accum_direct_f (u32 sub_phase) +{ + // Select target + if (SE_SUN_LUMINANCE==sub_phase) { + accum_direct_lum (); + return ; + } + phase_accumulator (); + u_setrt (rt_Generic_0,NULL,NULL,HW.pBaseZB); + + // *** assume accumulator setted up *** + light* fuckingsun = (light*)RImplementation.Lights.sun_adapted._get() ; + + // Common calc for quad-rendering + u32 Offset; + u32 C = color_rgba (255,255,255,255); + float _w = float (Device.dwWidth); + float _h = float (Device.dwHeight); + Fvector2 p0,p1; + p0.set (.5f/_w, .5f/_h); + p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + float d_Z = EPS_S, d_W = 1.f; + + // Common constants (light-related) + Fvector L_dir,L_clr; float L_spec; + L_clr.set (fuckingsun->color.r,fuckingsun->color.g,fuckingsun->color.b); + L_spec = u_diffuse2s (L_clr); + Device.mView.transform_dir (L_dir,fuckingsun->direction); + L_dir.normalize (); + + // Perform masking (only once - on the first/near phase) + RCache.set_CullMode (CULL_NONE ); + if (SE_SUN_NEAR==sub_phase) //. + { + // For sun-filter - clear to zero + CHK_DX (HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0L)); + + // Fill vertex buffer + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); + pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p0.y); pv++; + pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p1.y); pv++; + pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p0.y); pv++; + pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p1.y); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + RCache.set_Geometry (g_combine); + + // setup + float intensity = 0.3f*fuckingsun->color.r + 0.48f*fuckingsun->color.g + 0.22f*fuckingsun->color.b; + Fvector dir = L_dir; + dir.normalize().mul (- _sqrt(intensity+EPS)); + RCache.set_Element (s_accum_mask->E[SE_MASK_DIRECT]); // masker + RCache.set_c ("Ldynamic_dir", dir.x,dir.y,dir.z,0 ); + + // if (stencil>=1 && aref_pass) stencil = light_id + RCache.set_ColorWriteEnable (FALSE ); + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0x01,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE,D3DSTENCILOP_KEEP); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + + // recalculate d_Z, to perform depth-clipping + Fvector center_pt; center_pt.mad (Device.vCameraPosition,Device.vCameraDirection,ps_r2_sun_near); + Device.mFullTransform.transform(center_pt) ; + d_Z = center_pt.z ; + + // nv-stencil recompression + if (RImplementation.o.nvstencil && (SE_SUN_NEAR==sub_phase)) u_stencil_optimize(); //. driver bug? + + // Perform lighting + { + u_setrt (rt_Generic_0,NULL,NULL,HW.pBaseZB); // enshure RT setup + RCache.set_CullMode (CULL_NONE ); + RCache.set_ColorWriteEnable (); + + // texture adjustment matrix + float fTexelOffs = (.5f / float(RImplementation.o.smapsize)); + float fRange = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_scale:ps_r2_sun_depth_far_scale; + //float fBias = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_bias:ps_r2_sun_depth_far_bias; + // TODO: DX10: Remove this when fix inverse culling for far region + float fBias = (SE_SUN_NEAR==sub_phase)?ps_r2_sun_depth_near_bias:-ps_r2_sun_depth_far_bias; + Fmatrix m_TexelAdjust = + { + 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f * fRange, 0.0f, + 0.5f + fTexelOffs, 0.5f + fTexelOffs, 0.5f + fBias, 1.0f + }; + + // compute xforms + Fmatrix m_shadow; + { + FPU::m64r (); + Fmatrix xf_invview; xf_invview.invert (Device.mView) ; + Fmatrix xf_project; xf_project.mul (m_TexelAdjust,fuckingsun->X.D.combine); + m_shadow.mul (xf_project, xf_invview); + + // tsm-bias + if (SE_SUN_FAR == sub_phase) + { + Fvector bias; bias.mul (L_dir,ps_r2_sun_tsm_bias); + Fmatrix bias_t; bias_t.translate(bias); + m_shadow.mulB_44 (bias_t); + } + FPU::m24r (); + } + + // Make jitter texture + Fvector2 j0,j1; + float scale_X = float(Device.dwWidth) / float(TEX_jitter); + //float scale_Y = float(Device.dwHeight)/ float(TEX_jitter); + float offset = (.5f / float(TEX_jitter)); + j0.set (offset,offset); + j1.set (scale_X,scale_X).add(offset); + + // Fill vertex buffer + FVF::TL2uv* pv = (FVF::TL2uv*) RCache.Vertex.Lock (4,g_combine_2UV->vb_stride,Offset); + //pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p1.y, j0.x, j1.y); pv++; + //pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p0.y, j0.x, j0.y); pv++; + //pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p1.y, j1.x, j1.y); pv++; + //pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p0.y, j1.x, j0.y); pv++; + pv->set (-1, -1, d_Z, d_W, C, 0, 0, 0, 0); pv++; + pv->set (-1, 1, d_Z, d_W, C, 0, 1, 0, scale_X); pv++; + pv->set (1, -1, d_Z, d_W, C, 1, 0, scale_X, 0); pv++; + pv->set (1, 1, d_Z, d_W, C, 1, 1, scale_X, scale_X); pv++; + RCache.Vertex.Unlock (4,g_combine_2UV->vb_stride); + RCache.set_Geometry (g_combine_2UV); + + // setup + RCache.set_Element (s_accum_direct->E[sub_phase]); + RCache.set_c ("Ldynamic_dir", L_dir.x,L_dir.y,L_dir.z,0 ); + RCache.set_c ("Ldynamic_color", L_clr.x,L_clr.y,L_clr.z,L_spec ); + RCache.set_c ("m_shadow", m_shadow ); + + // setup stencil + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0xff,0x00); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + + // Igor: draw volumetric here + //accum_direct_volumetric (sub_phase, Offset); + } +} + +void CRenderTarget::accum_direct_lum () +{ + // TODO: DX10: Remove half pixel offset + // Select target + phase_accumulator (); + + // *** assume accumulator setted up *** + light* fuckingsun = (light*)RImplementation.Lights.sun_adapted._get() ; + + // Common calc for quad-rendering + u32 Offset; + // u32 C = color_rgba (255,255,255,255); + float _w = float (Device.dwWidth); + float _h = float (Device.dwHeight); + Fvector2 p0,p1; + p0.set (.5f/_w, .5f/_h); + p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + float d_Z = EPS_S; //, d_W = 1.f; + + // Common constants (light-related) + Fvector L_dir,L_clr; float L_spec; + L_clr.set (fuckingsun->color.r,fuckingsun->color.g,fuckingsun->color.b); + L_spec = u_diffuse2s (L_clr); + Device.mView.transform_dir (L_dir,fuckingsun->direction); + L_dir.normalize (); + + // recalculate d_Z, to perform depth-clipping + Fvector center_pt; center_pt.mad (Device.vCameraPosition,Device.vCameraDirection,ps_r2_sun_near); + Device.mFullTransform.transform(center_pt) ; + d_Z = center_pt.z ; + + // nv-stencil recompression + /* + if (RImplementation.o.nvstencil && (SE_SUN_NEAR==sub_phase)) u_stencil_optimize(); //. driver bug? + */ + + // Perform lighting + RCache.set_CullMode (CULL_NONE ); + RCache.set_ColorWriteEnable (); + + // Make jitter texture + Fvector2 j0,j1; + float scale_X = float(Device.dwWidth) / float(TEX_jitter); +// float scale_Y = float(Device.dwHeight)/ float(TEX_jitter); + float offset = (.5f / float(TEX_jitter)); + j0.set (offset,offset); + j1.set (scale_X,scale_X).add(offset); + + struct v_aa { + Fvector4 p; + Fvector2 uv0; + Fvector2 uvJ; + Fvector2 uv1; + Fvector2 uv2; + Fvector2 uv3; + Fvector4 uv4; + Fvector4 uv5; + }; + float smooth = 0.6f; + float ddw = smooth/_w; + float ddh = smooth/_h; + + // Fill vertex buffer + VERIFY (sizeof(v_aa)==g_aa_AA->vb_stride); + v_aa* pv = (v_aa*) RCache.Vertex.Lock (4,g_aa_AA->vb_stride,Offset); + pv->p.set(EPS, float(_h+EPS), EPS,1.f); pv->uv0.set(p0.x, p1.y);pv->uvJ.set(j0.x, j1.y);pv->uv1.set(p0.x-ddw,p1.y-ddh);pv->uv2.set(p0.x+ddw,p1.y+ddh);pv->uv3.set(p0.x+ddw,p1.y-ddh);pv->uv4.set(p0.x-ddw,p1.y+ddh,0,0);pv->uv5.set(0,0,0,0);pv++; + pv->p.set(EPS, EPS, EPS,1.f); pv->uv0.set(p0.x, p0.y);pv->uvJ.set(j0.x, j0.y);pv->uv1.set(p0.x-ddw,p0.y-ddh);pv->uv2.set(p0.x+ddw,p0.y+ddh);pv->uv3.set(p0.x+ddw,p0.y-ddh);pv->uv4.set(p0.x-ddw,p0.y+ddh,0,0);pv->uv5.set(0,0,0,0);pv++; + pv->p.set(float(_w+EPS),float(_h+EPS), EPS,1.f); pv->uv0.set(p1.x, p1.y);pv->uvJ.set(j1.x, j1.y);pv->uv1.set(p1.x-ddw,p1.y-ddh);pv->uv2.set(p1.x+ddw,p1.y+ddh);pv->uv3.set(p1.x+ddw,p1.y-ddh);pv->uv4.set(p1.x-ddw,p1.y+ddh,0,0);pv->uv5.set(0,0,0,0);pv++; + pv->p.set(float(_w+EPS),EPS, EPS,1.f); pv->uv0.set(p1.x, p0.y);pv->uvJ.set(j1.x, j0.y);pv->uv1.set(p1.x-ddw,p0.y-ddh);pv->uv2.set(p1.x+ddw,p0.y+ddh);pv->uv3.set(p1.x+ddw,p0.y-ddh);pv->uv4.set(p1.x-ddw,p0.y+ddh,0,0);pv->uv5.set(0,0,0,0);pv++; + RCache.Vertex.Unlock (4,g_aa_AA->vb_stride); + RCache.set_Geometry (g_aa_AA); + + // setup + RCache.set_Element (s_accum_direct->E[SE_SUN_LUMINANCE]); + RCache.set_c ("Ldynamic_dir", L_dir.x,L_dir.y,L_dir.z,0 ); + RCache.set_c ("Ldynamic_color", L_clr.x,L_clr.y,L_clr.z,L_spec ); + + // setup stencil + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0xff,0x00); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); +} + +void CRenderTarget::accum_direct_volumetric (u32 sub_phase, const u32 Offset, const Fmatrix &mShadow) +{ + if (!need_to_render_sunshafts()) + return; + + // Test. draw only for near part +// if (sub_phase!=SE_SUN_N/EAR) return; +// if (sub_phase!=SE_SUN_FAR) return; + + if ( (sub_phase!=SE_SUN_NEAR) && (sub_phase!=SE_SUN_FAR) ) return; + + phase_vol_accumulator(); + + RCache.set_ColorWriteEnable(); + + // Perform lighting + { + + // *** assume accumulator setted up *** + light* fuckingsun = (light*)RImplementation.Lights.sun_adapted._get() ; + + // Common constants (light-related) + Fvector L_clr; + L_clr.set (fuckingsun->color.r,fuckingsun->color.g,fuckingsun->color.b); + + // Use g_combine_2UV that was set up by accum_direct + // RCache.set_Geometry (g_combine_2UV); + + // setup + //RCache.set_Element (s_accum_direct_volumetric->E[sub_phase]); + RCache.set_Element (s_accum_direct_volumetric->E[0]); +// RCache.set_c ("Ldynamic_dir", L_dir.x,L_dir.y,L_dir.z,0 ); + RCache.set_c ("Ldynamic_color", L_clr.x,L_clr.y,L_clr.z,0); + RCache.set_c ("m_shadow", mShadow); +// RCache.set_c ("m_sunmask", m_clouds_shadow); + + // nv-DBT + float zMin,zMax; + if (SE_SUN_NEAR==sub_phase) { + zMin = 0; + zMax = ps_r2_sun_near; + } else { + extern float OLES_SUN_LIMIT_27_01_07; + zMin = ps_r2_sun_near; + zMax = OLES_SUN_LIMIT_27_01_07; + } + + RCache.set_c("volume_range", zMin, zMax, 0, 0); + + Fvector center_pt; + center_pt.mad(Device.vCameraPosition,Device.vCameraDirection,zMin); + Device.mFullTransform.transform(center_pt); + zMin = center_pt.z ; + + center_pt.mad(Device.vCameraPosition,Device.vCameraDirection,zMax); + Device.mFullTransform.transform (center_pt); + zMax = center_pt.z ; + +// TODO: DX10: Check if DX10 has analog for NV DBT +// if (u_DBT_enable(zMin,zMax)) { + // z-test always +// HW.pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); +// HW.pDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); +// } +// else + { + +// TODO: DX10: Implement via different passes + if (SE_SUN_NEAR==sub_phase) + //HW.pDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_GREATER); + RCache.set_ZFunc(D3DCMP_GREATER); + else + //HW.pDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL); + RCache.set_ZFunc(D3DCMP_LESSEQUAL); + } + + // Fetch4 : enable +// if (RImplementation.o.HW_smap_FETCH4) { + //. we hacked the shader to force smap on S0 +//# define FOURCC_GET4 MAKEFOURCC('G','E','T','4') +// HW.pDevice->SetSamplerState ( 0, D3DSAMP_MIPMAPLODBIAS, FOURCC_GET4 ); +// } + + // setup stencil: we have to draw to both lit and unlit pixels + //RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0xff,0x00); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + + // Fetch4 : disable +// if (RImplementation.o.HW_smap_FETCH4) { + //. we hacked the shader to force smap on S0 +//# define FOURCC_GET1 MAKEFOURCC('G','E','T','1') +// HW.pDevice->SetSamplerState ( 0, D3DSAMP_MIPMAPLODBIAS, FOURCC_GET1 ); +// } + +// TODO: DX10: Check if DX10 has analog for NV DBT + // disable depth bounds +// u_DBT_disable (); + } +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_omnipart_geom.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_omnipart_geom.cpp new file mode 100644 index 00000000000..ec4e2f979d4 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_omnipart_geom.cpp @@ -0,0 +1,30 @@ +#include "stdafx.h" +#include "../xrRender/du_sphere_part.h" + +void CRenderTarget::accum_omnip_geom_create () +{ + u32 dwUsage = GL_STATIC_DRAW; + + // vertices + { + u32 vCount = DU_SPHERE_PART_NUMVERTEX; + u32 vSize = 3*4; + glGenBuffers(1, &g_accum_omnip_vb); + glBindBuffer(GL_ARRAY_BUFFER, g_accum_omnip_vb); + CHK_GL(glBufferData(GL_ARRAY_BUFFER, vCount*vSize, du_sphere_part_vertices, dwUsage)); + } + + // Indices + { + u32 iCount = DU_SPHERE_PART_NUMFACES*3; + glGenBuffers(1, &g_accum_omnip_ib); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_accum_omnip_ib); + CHK_GL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, iCount * 2, du_sphere_part_faces, dwUsage)); + } +} + +void CRenderTarget::accum_omnip_geom_destroy() +{ + glDeleteBuffers(1, &g_accum_omnip_vb); + glDeleteBuffers(1, &g_accum_omnip_ib); +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_point.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_point.cpp new file mode 100644 index 00000000000..22b2964460d --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_point.cpp @@ -0,0 +1,117 @@ +#include "stdafx.h" + +void CRenderTarget::accum_point (light* L) +{ + phase_accumulator (); + RImplementation.stats.l_visible ++; + + ref_shader shader = L->s_point; + if (!shader) shader = s_accum_point; + + // Common + Fvector L_pos; + float L_spec; + //float L_R = L->range; + float L_R = L->range*.95f; + Fvector L_clr; L_clr.set (L->color.r,L->color.g,L->color.b); + L_spec = u_diffuse2s (L_clr); + Device.mView.transform_tiny (L_pos,L->position); + + // Xforms + L->xform_calc (); + RCache.set_xform_world (L->m_xform); + RCache.set_xform_view (Device.mView); + RCache.set_xform_project (Device.mProject); + enable_scissor (L); + enable_dbt_bounds (L); + + // ***************************** Mask by stencil ************************************* + // *** similar to "Carmack's reverse", but assumes convex, non intersecting objects, + // *** thus can cope without stencil clear with 127 lights + // *** in practice, 'cause we "clear" it back to 0x1 it usually allows us to > 200 lights :) + RCache.set_Element (s_accum_mask->E[SE_MASK_POINT]); // masker + RCache.set_ColorWriteEnable (FALSE); + + // backfaces: if (1<=stencil && zfail) stencil = light_id + RCache.set_CullMode (CULL_CW); + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0x01,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE); + draw_volume (L); + + // frontfaces: if (1<=stencil && zfail) stencil = 0x1 + RCache.set_CullMode (CULL_CCW); + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE); + draw_volume (L); + + // nv-stencil recompression + if (RImplementation.o.nvstencil) u_stencil_optimize(); + + // ***************************** Minimize overdraw ************************************* + // Select shader (front or back-faces), *** back, if intersect near plane + RCache.set_ColorWriteEnable (); + RCache.set_CullMode (CULL_CW); // back + /* + if (bIntersect) RCache.set_CullMode (CULL_CW); // back + else RCache.set_CullMode (CULL_CCW); // front + */ + + // 2D texgens + Fmatrix m_Texgen; u_compute_texgen_screen (m_Texgen ); + Fmatrix m_Texgen_J; u_compute_texgen_jitter (m_Texgen_J ); + + // Draw volume with projective texgen + { + // Select shader + u32 _id = 0; + if (L->flags.bShadow) { + bool bFullSize = (L->X.S.size == u32(RImplementation.o.smapsize)); + if (L->X.S.transluent) _id = SE_L_TRANSLUENT; + else if (bFullSize) _id = SE_L_FULLSIZE; + else _id = SE_L_NORMAL; + } else { + _id = SE_L_UNSHADOWED; + //m_Shadow = m_Lmap; + } + RCache.set_Element (shader->E[ _id ] ); + + // Constants + RCache.set_c ("Ldynamic_pos", L_pos.x,L_pos.y,L_pos.z,1/(L_R*L_R)); + RCache.set_c ("Ldynamic_color", L_clr.x,L_clr.y,L_clr.z,L_spec); + RCache.set_c ("m_texgen", m_Texgen); + + // Fetch4 : enable +// if (RImplementation.o.HW_smap_FETCH4) { + //. we hacked the shader to force smap on S0 +//# define FOURCC_GET4 MAKEFOURCC('G','E','T','4') +// HW.pDevice->SetSamplerState ( 0, D3DSAMP_MIPMAPLODBIAS, FOURCC_GET4 ); +// } + + RCache.set_CullMode (CULL_CW); // back + // Render if (light_id <= stencil && z-pass) + RCache.set_Stencil(TRUE,D3DCMP_EQUAL,dwLightMarkerID,0xff,0x00); + draw_volume (L); + + // Fetch4 : disable +// if (RImplementation.o.HW_smap_FETCH4) { + //. we hacked the shader to force smap on S0 +//# define FOURCC_GET1 MAKEFOURCC('G','E','T','1') +// HW.pDevice->SetSamplerState ( 0, D3DSAMP_MIPMAPLODBIAS, FOURCC_GET1 ); +// } + } + + // blend-copy + if (!RImplementation.o.fp16_blend) { + u_setrt (rt_Accumulator,NULL,NULL,HW.pBaseZB); + RCache.set_Element (s_accum_mask->E[SE_MASK_ACCUM_VOL] ); + RCache.set_c ("m_texgen", m_Texgen); + RCache.set_Stencil(TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0xff,0x00); + draw_volume (L); + } + + //CHK_DX (HW.pDevice->SetRenderState(D3DRS_SCISSORTESTENABLE,FALSE)); + RCache.set_Scissor(0); + + //dwLightMarkerID += 2; // keep lowest bit always setted up + increment_light_marker(); + + u_DBT_disable (); +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_point_geom.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_point_geom.cpp new file mode 100644 index 00000000000..17bc928bb73 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_point_geom.cpp @@ -0,0 +1,312 @@ +#include "stdafx.h" + +#include "../xrRender/du_sphere.h" + +/* +Fvector du_sphere_vertices[DU_SPHERE_NUMVERTEX]= +{ + 0.0000f, 1.0000f, 0.0000f, + 0.8944f, 0.4472f, 0.0000f, + 0.2764f, 0.4472f, 0.8507f, + -0.7236f, 0.4472f, 0.5257f, + -0.7236f, 0.4472f, -0.5257f, + 0.2764f, 0.4472f, -0.8507f, + 0.7236f, -0.4472f, 0.5257f, + -0.2764f, -0.4472f, 0.8507f, + -0.8944f, -0.4472f, -0.0000f, + -0.2764f, -0.4472f, -0.8507f, + 0.7236f, -0.4472f, -0.5257f, + 0.0000f, -1.0000f, 0.0000f, + 0.3607f, 0.9327f, 0.0000f, + 0.6729f, 0.7397f, 0.0000f, + 0.1115f, 0.9327f, 0.3431f, + 0.2079f, 0.7397f, 0.6399f, + -0.2918f, 0.9327f, 0.2120f, + -0.5444f, 0.7397f, 0.3955f, + -0.2918f, 0.9327f, -0.2120f, + -0.5444f, 0.7397f, -0.3955f, + 0.1115f, 0.9327f, -0.3431f, + 0.2079f, 0.7397f, -0.6399f, + 0.7844f, 0.5168f, 0.3431f, + 0.5687f, 0.5168f, 0.6399f, + -0.0839f, 0.5168f, 0.8520f, + -0.4329f, 0.5168f, 0.7386f, + -0.8362f, 0.5168f, 0.1835f, + -0.8362f, 0.5168f, -0.1835f, + -0.4329f, 0.5168f, -0.7386f, + -0.0839f, 0.5168f, -0.8520f, + 0.5687f, 0.5168f, -0.6399f, + 0.7844f, 0.5168f, -0.3431f, + 0.9647f, 0.1561f, 0.2120f, + 0.9051f, -0.1561f, 0.3955f, + 0.0965f, 0.1561f, 0.9830f, + -0.0965f, -0.1561f, 0.9830f, + -0.9051f, 0.1561f, 0.3955f, + -0.9647f, -0.1561f, 0.2120f, + -0.6558f, 0.1561f, -0.7386f, + -0.4998f, -0.1561f, -0.8520f, + 0.4998f, 0.1561f, -0.8520f, + 0.6558f, -0.1561f, -0.7386f, + 0.9647f, 0.1561f, -0.2120f, + 0.9051f, -0.1561f, -0.3955f, + 0.4998f, 0.1561f, 0.8520f, + 0.6558f, -0.1561f, 0.7386f, + -0.6558f, 0.1561f, 0.7386f, + -0.4998f, -0.1561f, 0.8520f, + -0.9051f, 0.1561f, -0.3955f, + -0.9647f, -0.1561f, -0.2120f, + 0.0965f, 0.1561f, -0.9830f, + -0.0965f, -0.1561f, -0.9830f, + 0.4329f, -0.5168f, 0.7386f, + 0.0839f, -0.5168f, 0.8520f, + -0.5687f, -0.5168f, 0.6399f, + -0.7844f, -0.5168f, 0.3431f, + -0.7844f, -0.5168f, -0.3431f, + -0.5687f, -0.5168f, -0.6399f, + 0.0839f, -0.5168f, -0.8520f, + 0.4329f, -0.5168f, -0.7386f, + 0.8362f, -0.5168f, -0.1835f, + 0.8362f, -0.5168f, 0.1835f, + 0.2918f, -0.9327f, 0.2120f, + 0.5444f, -0.7397f, 0.3955f, + -0.1115f, -0.9327f, 0.3431f, + -0.2079f, -0.7397f, 0.6399f, + -0.3607f, -0.9327f, -0.0000f, + -0.6729f, -0.7397f, -0.0000f, + -0.1115f, -0.9327f, -0.3431f, + -0.2079f, -0.7397f, -0.6399f, + 0.2918f, -0.9327f, -0.2120f, + 0.5444f, -0.7397f, -0.3955f, + 0.4795f, 0.8054f, 0.3484f, + -0.1832f, 0.8054f, 0.5637f, + -0.5927f, 0.8054f, -0.0000f, + -0.1832f, 0.8054f, -0.5637f, + 0.4795f, 0.8054f, -0.3484f, + 0.9855f, -0.1699f, 0.0000f, + 0.3045f, -0.1699f, 0.9372f, + -0.7973f, -0.1699f, 0.5792f, + -0.7973f, -0.1699f, -0.5792f, + 0.3045f, -0.1699f, -0.9372f, + 0.7973f, 0.1699f, 0.5792f, + -0.3045f, 0.1699f, 0.9372f, + -0.9855f, 0.1699f, -0.0000f, + -0.3045f, 0.1699f, -0.9372f, + 0.7973f, 0.1699f, -0.5792f, + 0.1832f, -0.8054f, 0.5637f, + -0.4795f, -0.8054f, 0.3484f, + -0.4795f, -0.8054f, -0.3484f, + 0.1832f, -0.8054f, -0.5637f, + 0.5927f, -0.8054f, 0.0000 +}; + +u16 du_sphere_faces[DU_SPHERE_NUMFACES*3]={ + 14, 12, 0, + 72, 13, 12, + 14, 72, 12, + 15, 72, 14, + 22, 1, 13, + 72, 22, 13, + 23, 22, 72, + 15, 23, 72, + 2, 23, 15, + 16, 14, 0, + 73, 15, 14, + 16, 73, 14, + 17, 73, 16, + 24, 2, 15, + 73, 24, 15, + 25, 24, 73, + 17, 25, 73, + 3, 25, 17, + 18, 16, 0, + 74, 17, 16, + 18, 74, 16, + 19, 74, 18, + 26, 3, 17, + 74, 26, 17, + 27, 26, 74, + 19, 27, 74, + 4, 27, 19, + 20, 18, 0, + 75, 19, 18, + 20, 75, 18, + 21, 75, 20, + 28, 4, 19, + 75, 28, 19, + 29, 28, 75, + 21, 29, 75, + 5, 29, 21, + 12, 20, 0, + 76, 21, 20, + 12, 76, 20, + 13, 76, 12, + 30, 5, 21, + 76, 30, 21, + 31, 30, 76, + 13, 31, 76, + 1, 31, 13, + 32, 42, 1, + 77, 43, 42, + 32, 77, 42, + 33, 77, 32, + 60, 10, 43, + 77, 60, 43, + 61, 60, 77, + 33, 61, 77, + 6, 61, 33, + 34, 44, 2, + 78, 45, 44, + 34, 78, 44, + 35, 78, 34, + 52, 6, 45, + 78, 52, 45, + 53, 52, 78, + 35, 53, 78, + 7, 53, 35, + 36, 46, 3, + 79, 47, 46, + 36, 79, 46, + 37, 79, 36, + 54, 7, 47, + 79, 54, 47, + 55, 54, 79, + 37, 55, 79, + 8, 55, 37, + 38, 48, 4, + 80, 49, 48, + 38, 80, 48, + 39, 80, 38, + 56, 8, 49, + 80, 56, 49, + 57, 56, 80, + 39, 57, 80, + 9, 57, 39, + 40, 50, 5, + 81, 51, 50, + 40, 81, 50, + 41, 81, 40, + 58, 9, 51, + 81, 58, 51, + 59, 58, 81, + 41, 59, 81, + 10, 59, 41, + 33, 45, 6, + 82, 44, 45, + 33, 82, 45, + 32, 82, 33, + 23, 2, 44, + 82, 23, 44, + 22, 23, 82, + 32, 22, 82, + 1, 22, 32, + 35, 47, 7, + 83, 46, 47, + 35, 83, 47, + 34, 83, 35, + 25, 3, 46, + 83, 25, 46, + 24, 25, 83, + 34, 24, 83, + 2, 24, 34, + 37, 49, 8, + 84, 48, 49, + 37, 84, 49, + 36, 84, 37, + 27, 4, 48, + 84, 27, 48, + 26, 27, 84, + 36, 26, 84, + 3, 26, 36, + 39, 51, 9, + 85, 50, 51, + 39, 85, 51, + 38, 85, 39, + 29, 5, 50, + 85, 29, 50, + 28, 29, 85, + 38, 28, 85, + 4, 28, 38, + 41, 43, 10, + 86, 42, 43, + 41, 86, 43, + 40, 86, 41, + 31, 1, 42, + 86, 31, 42, + 30, 31, 86, + 40, 30, 86, + 5, 30, 40, + 62, 64, 11, + 87, 65, 64, + 62, 87, 64, + 63, 87, 62, + 53, 7, 65, + 87, 53, 65, + 52, 53, 87, + 63, 52, 87, + 6, 52, 63, + 64, 66, 11, + 88, 67, 66, + 64, 88, 66, + 65, 88, 64, + 55, 8, 67, + 88, 55, 67, + 54, 55, 88, + 65, 54, 88, + 7, 54, 65, + 66, 68, 11, + 89, 69, 68, + 66, 89, 68, + 67, 89, 66, + 57, 9, 69, + 89, 57, 69, + 56, 57, 89, + 67, 56, 89, + 8, 56, 67, + 68, 70, 11, + 90, 71, 70, + 68, 90, 70, + 69, 90, 68, + 59, 10, 71, + 90, 59, 71, + 58, 59, 90, + 69, 58, 90, + 9, 58, 69, + 70, 62, 11, + 91, 63, 62, + 70, 91, 62, + 71, 91, 70, + 61, 6, 63, + 91, 61, 63, + 60, 61, 91, + 71, 60, 91, + 10, 60, 71, +}; +*/ + +void CRenderTarget::accum_point_geom_create() +{ + u32 dwUsage = GL_STATIC_DRAW; + + // vertices + { + u32 vCount = DU_SPHERE_NUMVERTEX; + u32 vSize = 3*4; + glGenBuffers(1, &g_accum_point_vb); + glBindBuffer(GL_ARRAY_BUFFER, g_accum_point_vb); + CHK_GL(glBufferData(GL_ARRAY_BUFFER, vCount*vSize, du_sphere_vertices, dwUsage)); + } + + // Indices + { + u32 iCount = DU_SPHERE_NUMFACES*3; + glGenBuffers(1, &g_accum_point_ib); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_accum_point_ib); + CHK_GL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, iCount*2, du_sphere_faces, dwUsage)); + } +} + +void CRenderTarget::accum_point_geom_destroy() +{ + glDeleteBuffers(1, &g_accum_point_vb); + glDeleteBuffers(1, &g_accum_point_ib); +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_reflected.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_reflected.cpp new file mode 100644 index 00000000000..9aea86c03b6 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_reflected.cpp @@ -0,0 +1,78 @@ +#include "stdafx.h" + +void CRenderTarget::accum_reflected (light* L) +{ + phase_accumulator (); + RImplementation.stats.l_visible ++; + + // *** assume accumulator setted up *** + // ***************************** Mask by stencil ************************************* + ref_shader shader = s_accum_reflected; + + BOOL bIntersect = FALSE; //enable_scissor(L); + L->xform_calc (); + RCache.set_xform_world (L->m_xform ); + RCache.set_xform_view (Device.mView ); + RCache.set_xform_project (Device.mProject ); + bIntersect = enable_scissor (L); + enable_dbt_bounds (L); + + // ***************************** Minimize overdraw ************************************* + // Select shader (front or back-faces), *** back, if intersect near plane + RCache.set_ColorWriteEnable (); + if (bIntersect) RCache.set_CullMode (CULL_CW); // back + else RCache.set_CullMode (CULL_CCW); // front + + // 2D texgen (texture adjustment matrix) + Fmatrix m_Texgen; + { + float _w = float(Device.dwWidth); + float _h = float(Device.dwHeight); + float o_w = (.5f / _w); + float o_h = (.5f / _h); + Fmatrix m_TexelAdjust = + { + 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.5f + o_w, 0.5f + o_h, 0.0f, 1.0f + }; + m_Texgen.mul (m_TexelAdjust,RCache.xforms.m_wvp); + } + + // Common constants + Fvector L_dir,L_clr,L_pos; float L_spec; + L_clr.set (L->color.r,L->color.g,L->color.b); + L_spec = u_diffuse2s (L_clr); + Device.mView.transform_tiny (L_pos,L->position); + Device.mView.transform_dir (L_dir,L->direction); + L_dir.normalize (); + + { + // Lighting + RCache.set_Shader (shader); + + // Constants + RCache.set_c ("Ldynamic_pos", L_pos.x,L_pos.y,L_pos.z,1/(L->range*L->range)); + RCache.set_c ("Ldynamic_color", L_clr.x,L_clr.y,L_clr.z,L_spec); + RCache.set_c ("direction", L_dir.x,L_dir.y,L_dir.z,0); + RCache.set_c ("m_texgen", m_Texgen); + + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); + draw_volume (L); + } + + // blend-copy + if (!RImplementation.o.fp16_blend) { + u_setrt (rt_Accumulator,NULL,NULL,HW.pBaseZB); + RCache.set_Element (s_accum_mask->E[SE_MASK_ACCUM_VOL] ); + RCache.set_c ("m_texgen", m_Texgen); + + // per pixel + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); + draw_volume (L); + } + + // + u_DBT_disable (); +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_spot.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_spot.cpp new file mode 100644 index 00000000000..d48aa985a14 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_spot.cpp @@ -0,0 +1,458 @@ +#include "stdafx.h" +#include "../xrRender/du_cone.h" + +//extern Fvector du_cone_vertices[DU_CONE_NUMVERTEX]; + +void CRenderTarget::accum_spot (light* L) +{ + phase_accumulator (); + RImplementation.stats.l_visible ++; + + // *** assume accumulator setted up *** + // ***************************** Mask by stencil ************************************* + ref_shader shader; + if (IRender_Light::OMNIPART == L->flags.type) { + shader = L->s_point; + if (!shader) shader = s_accum_point; + } + else { + shader = L->s_spot; + if (!shader) shader = s_accum_spot; + } + + BOOL bIntersect = FALSE; //enable_scissor(L); + { + // setup xform + L->xform_calc (); + RCache.set_xform_world (L->m_xform ); + RCache.set_xform_view (Device.mView ); + RCache.set_xform_project (Device.mProject ); + bIntersect = enable_scissor (L); + enable_dbt_bounds (L); + + // *** similar to "Carmack's reverse", but assumes convex, non intersecting objects, + // *** thus can cope without stencil clear with 127 lights + // *** in practice, 'cause we "clear" it back to 0x1 it usually allows us to > 200 lights :) + RCache.set_ColorWriteEnable (FALSE); + RCache.set_Element (s_accum_mask->E[SE_MASK_SPOT]); // masker + + // backfaces: if (stencil>=1 && zfail) stencil = light_id + RCache.set_CullMode (CULL_CW); + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0x01,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE); + draw_volume (L); + + // frontfaces: if (stencil>=light_id && zfail) stencil = 0x1 + RCache.set_CullMode (CULL_CCW); + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE); + draw_volume (L); + } + + // nv-stencil recompression + if (RImplementation.o.nvstencil) u_stencil_optimize(); + + // ***************************** Minimize overdraw ************************************* + // Select shader (front or back-faces), *** back, if intersect near plane + RCache.set_ColorWriteEnable (); + RCache.set_CullMode (CULL_CW); // back + + // 2D texgens + Fmatrix m_Texgen; u_compute_texgen_screen (m_Texgen ); + Fmatrix m_Texgen_J; u_compute_texgen_jitter (m_Texgen_J ); + + // Shadow xform (+texture adjustment matrix) + Fmatrix m_Shadow,m_Lmap; + { + float smapsize = float(RImplementation.o.smapsize); + float fTexelOffs = (.5f / smapsize); + float view_dim = float(L->X.S.size-2)/smapsize; + float view_sx = float(L->X.S.posX+1)/smapsize; + float view_sy = float(L->X.S.posY+1)/smapsize; + float fRange = float(1.f)*ps_r2_ls_depth_scale; + float fBias = ps_r2_ls_depth_bias; + Fmatrix m_TexelAdjust = { + view_dim/2.f, 0.0f, 0.0f, 0.0f, + 0.0f, view_dim/2.f, 0.0f, 0.0f, + 0.0f, 0.0f, view_dim/2.f * fRange, 0.0f, + view_dim/2.f + view_sx + fTexelOffs, view_dim/2.f + view_sy + fTexelOffs, view_dim/2.f + fBias, 1.0f + }; + + // compute xforms + Fmatrix xf_world; xf_world.invert (Device.mView); + Fmatrix xf_view = L->X.S.view; + Fmatrix xf_project; xf_project.mul (m_TexelAdjust,L->X.S.project); + m_Shadow.mul (xf_view, xf_world); + m_Shadow.mulA_44 (xf_project ); + + // lmap + view_dim = 1.f; + view_sx = 0.f; + view_sy = 0.f; + Fmatrix m_TexelAdjust2 = { + view_dim/2.f, 0.0f, 0.0f, 0.0f, + 0.0f, view_dim/2.f, 0.0f, 0.0f, + 0.0f, 0.0f, view_dim/2.f * fRange, 0.0f, + view_dim/2.f + view_sx + fTexelOffs, view_dim/2.f + view_sy + fTexelOffs, view_dim/2.f + fBias, 1.0f + }; + + // compute xforms + xf_project.mul (m_TexelAdjust2,L->X.S.project); + m_Lmap.mul (xf_view, xf_world); + m_Lmap.mulA_44 (xf_project ); + } + + // Common constants + Fvector L_dir,L_clr,L_pos; float L_spec; + L_clr.set (L->color.r,L->color.g,L->color.b); + L_clr.mul (L->get_LOD()); + L_spec = u_diffuse2s (L_clr); + Device.mView.transform_tiny (L_pos,L->position); + Device.mView.transform_dir (L_dir,L->direction); + L_dir.normalize (); + + // Draw volume with projective texgen + { + // Select shader + u32 _id = 0; + if (L->flags.bShadow) { + bool bFullSize = (L->X.S.size == RImplementation.o.smapsize); + if (L->X.S.transluent) _id = SE_L_TRANSLUENT; + else if (bFullSize) _id = SE_L_FULLSIZE; + else _id = SE_L_NORMAL; + } else { + _id = SE_L_UNSHADOWED; + m_Shadow = m_Lmap; + } + RCache.set_Element (shader->E[ _id ] ); + + RCache.set_CullMode (CULL_CW); // back + + // Constants + float att_R = L->range*.95f; + float att_factor = 1.f/(att_R*att_R); + RCache.set_c ("Ldynamic_pos", L_pos.x,L_pos.y,L_pos.z,att_factor); + RCache.set_c ("Ldynamic_color", L_clr.x,L_clr.y,L_clr.z,L_spec); + RCache.set_c ("m_texgen", m_Texgen ); + RCache.set_c ("m_texgen_J", m_Texgen_J ); + RCache.set_c ("m_shadow", m_Shadow ); + RCache.set_ca ("m_lmap", 0, m_Lmap._11, m_Lmap._21, m_Lmap._31, m_Lmap._41 ); + RCache.set_ca ("m_lmap", 1, m_Lmap._12, m_Lmap._22, m_Lmap._32, m_Lmap._42 ); + + // Fetch4 : enable +// if (RImplementation.o.HW_smap_FETCH4) { + //. we hacked the shader to force smap on S0 +//# define FOURCC_GET4 MAKEFOURCC('G','E','T','4') +// HW.pDevice->SetSamplerState ( 0, D3DSAMP_MIPMAPLODBIAS, FOURCC_GET4 ); +// } + + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,dwLightMarkerID,0xff,0x00); + draw_volume (L); + + // Fetch4 : disable +// if (RImplementation.o.HW_smap_FETCH4) { + //. we hacked the shader to force smap on S0 +//# define FOURCC_GET1 MAKEFOURCC('G','E','T','1') +// HW.pDevice->SetSamplerState ( 0, D3DSAMP_MIPMAPLODBIAS, FOURCC_GET1 ); +// } + } + + // blend-copy + if (!RImplementation.o.fp16_blend) { + u_setrt (rt_Accumulator,NULL,NULL,HW.pBaseZB); + RCache.set_Element (s_accum_mask->E[SE_MASK_ACCUM_VOL] ); + RCache.set_c ("m_texgen", m_Texgen); + RCache.set_c ("m_texgen_J", m_Texgen_J ); + RCache.set_Stencil (TRUE,D3DCMP_EQUAL,dwLightMarkerID,0xff,0x00); + draw_volume (L); + } + + RCache.set_Scissor(0); + //CHK_DX (HW.pDevice->SetRenderState(D3DRS_SCISSORTESTENABLE,FALSE)); + //dwLightMarkerID += 2; // keep lowest bit always setted up + increment_light_marker(); + + u_DBT_disable (); +} + +void CRenderTarget::accum_volumetric(light* L) +{ + //if (L->flags.type != IRender_Light::SPOT) return; + if (!L->flags.bVolumetric) return; + + phase_vol_accumulator(); + + ref_shader shader; + shader = L->s_volumetric; + if (!shader) + shader = s_accum_volume; + + // *** assume accumulator setted up *** + // ***************************** Mask by stencil ************************************* + BOOL bIntersect = FALSE; //enable_scissor(L); + { + // setup xform + L->xform_calc (); + RCache.set_xform_world (L->m_xform ); + RCache.set_xform_view (Device.mView ); + RCache.set_xform_project (Device.mProject ); + bIntersect = enable_scissor (L); + + //enable_dbt_bounds (L); + } + + RCache.set_ColorWriteEnable (); + RCache.set_CullMode (CULL_NONE); // back + + // 2D texgens + Fmatrix m_Texgen; u_compute_texgen_screen (m_Texgen ); + Fmatrix m_Texgen_J; u_compute_texgen_jitter (m_Texgen_J ); + + // Shadow xform (+texture adjustment matrix) + Fmatrix m_Shadow,m_Lmap; + Fmatrix mFrustumSrc; + CFrustum ClipFrustum; + { + float smapsize = float(RImplementation.o.smapsize); + float fTexelOffs = (.5f / smapsize); + float view_dim = float(L->X.S.size-2)/smapsize; + float view_sx = float(L->X.S.posX+1)/smapsize; + float view_sy = float(L->X.S.posY+1)/smapsize; + float fRange = float(1.f)*ps_r2_ls_depth_scale; + float fBias = ps_r2_ls_depth_bias; + Fmatrix m_TexelAdjust = { + view_dim/2.f, 0.0f, 0.0f, 0.0f, + 0.0f, view_dim/2.f, 0.0f, 0.0f, + 0.0f, 0.0f, view_dim/2.f * fRange, 0.0f, + view_dim/2.f + view_sx + fTexelOffs, view_dim/2.f + view_sy + fTexelOffs, view_dim/2.f + fBias, 1.0f + }; + + // compute xforms + Fmatrix xf_world; xf_world.invert (Device.mView); + Fmatrix xf_view = L->X.S.view; + Fmatrix xf_project; xf_project.mul (m_TexelAdjust,L->X.S.project); + m_Shadow.mul (xf_view, xf_world); + m_Shadow.mulA_44 (xf_project ); + + // lmap + view_dim = 1.f; + view_sx = 0.f; + view_sy = 0.f; + Fmatrix m_TexelAdjust2 = { + view_dim/2.f, 0.0f, 0.0f, 0.0f, + 0.0f, view_dim/2.f, 0.0f, 0.0f, + 0.0f, 0.0f, view_dim/2.f * fRange, 0.0f, + view_dim/2.f + view_sx + fTexelOffs, view_dim/2.f + view_sy + fTexelOffs, view_dim/2.f + fBias, 1.0f + }; + + // compute xforms + xf_project.mul (m_TexelAdjust2,L->X.S.project); + m_Lmap.mul (xf_view, xf_world); + m_Lmap.mulA_44 (xf_project ); + + // Compute light frustum in world space + mFrustumSrc.mul(L->X.S.project, xf_view); + ClipFrustum.CreateFromMatrix( mFrustumSrc, FRUSTUM_P_ALL); + // Adjust frustum far plane + // 4 - far, 5 - near + ClipFrustum.planes[4].d -= + (ClipFrustum.planes[4].d + ClipFrustum.planes[5].d)*(1-L->m_volumetric_distance); + + } + + // Calculate camera space AABB + // xform BB + /* + Fbox BB; + Fvector rr; rr.set(L->spatial.sphere.R,L->spatial.sphere.R,L->spatial.sphere.R); + BB.setb (L->spatial.sphere.P, rr); + + Fbox bbp; bbp.invalidate(); + for (u32 i=0; i<8; i++) { + Fvector pt; + BB.getpoint (i,pt); + //Device.mFullTransform.transform (pt); + Device.mFullTransform.transform (mView); + bbp.modify (pt); + } + */ + + + // Calculate camera space AABB + // Adjust AABB according to the adjusted distance for the light volume + Fbox aabb; + + //float scaledRadius = L->spatial.sphere.R * (1+L->m_volumetric_distance)*0.5f; + float scaledRadius = L->spatial.sphere.R * L->m_volumetric_distance; + Fvector rr = Fvector().set(scaledRadius,scaledRadius,scaledRadius); + Fvector pt = L->spatial.sphere.P; + pt.sub(L->position); + pt.mul(L->m_volumetric_distance); + pt.add(L->position); + // Don't adjust AABB + //float scaledRadius = L->spatial.sphere.R; + //Fvector rr = Fvector().set(scaledRadius,scaledRadius,scaledRadius); + //Fvector pt = L->spatial.sphere.P; + Device.mView.transform(pt); + aabb.setb( pt, rr); +/* + // Calculate presise AABB assuming we are drawing for the spot light + { + aabb.invalidate(); + Fmatrix transform; + transform.mul( Device.mView, L->m_xform); + for (u32 i=0; im_volumetric_quality; + int iNumSlises = (int)(VOLUMETRIC_SLICES*fQuality); + // min 10 surfaces + iNumSlises = _max(10, iNumSlises); + // Adjust slice intensity + fQuality = ((float)iNumSlises)/VOLUMETRIC_SLICES; + Fvector L_dir,L_clr,L_pos; float L_spec; + L_clr.set (L->color.r,L->color.g,L->color.b); + L_clr.mul (L->m_volumetric_intensity); + L_clr.mul (L->m_volumetric_distance); + L_clr.mul (1/fQuality); + L_clr.mul (L->get_LOD()); + L_spec = u_diffuse2s (L_clr); + Device.mView.transform_tiny (L_pos,L->position); + Device.mView.transform_dir (L_dir,L->direction); + L_dir.normalize (); + + // Draw volume with projective texgen + { + /* + // Select shader + u32 _id = 0; + if (L->flags.bShadow) { + bool bFullSize = (L->X.S.size == RImplementation.o.smapsize); + if (L->X.S.transluent) _id = SE_L_TRANSLUENT; + else if (bFullSize) _id = SE_L_FULLSIZE; + else _id = SE_L_NORMAL; + } else { + _id = SE_L_UNSHADOWED; + m_Shadow = m_Lmap; + } + RCache.set_Element (shader->E[ _id ] ); + */ + + RCache.set_Element (shader->E[0]); + + // Constants + float att_R = L->m_volumetric_distance*L->range*.95f; + float att_factor = 1.f/(att_R*att_R); + RCache.set_c ("Ldynamic_pos", L_pos.x,L_pos.y,L_pos.z,att_factor); + RCache.set_c ("Ldynamic_color", L_clr.x,L_clr.y,L_clr.z,L_spec); + RCache.set_c ("m_texgen", m_Texgen ); + RCache.set_c ("m_texgen_J", m_Texgen_J ); + RCache.set_c ("m_shadow", m_Shadow ); + RCache.set_ca ("m_lmap", 0, m_Lmap._11, m_Lmap._21, m_Lmap._31, m_Lmap._41 ); + RCache.set_ca ("m_lmap", 1, m_Lmap._12, m_Lmap._22, m_Lmap._32, m_Lmap._42 ); + RCache.set_c ("vMinBounds", aabb.x1, aabb.y1, aabb.z1, 0); + // Increase camera-space aabb z size to compensate decrease of slices number + RCache.set_c ("vMaxBounds", aabb.x2, aabb.y2, aabb.z1 + (aabb.z2-aabb.z1)/fQuality, 0); + + // Set up user clip planes + { + static shared_str strFrustumClipPlane("FrustumClipPlane"); + // TODO: DX10: Check if it's equivalent to the previouse code. + //RCache.set_ClipPlanes (TRUE,ClipFrustum.planes,ClipFrustum.p_count); + + // Transform frustum to clip space + Fmatrix PlaneTransform; + PlaneTransform.transpose(Device.mInvFullTransform); + //HW.pDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0x3F); + + for ( int i=0; i<6; ++i) + { + Fvector4 &ClipPlane = *(Fvector4*)&ClipFrustum.planes[i].n.x; + Fvector4 TransformedPlane; + PlaneTransform.transform(TransformedPlane, ClipPlane); + TransformedPlane.mul(-1.0f); + RCache.set_ca(strFrustumClipPlane, i, TransformedPlane); + //HW.pDevice->SetClipPlane( i, &TransformedPlane.x); + } + /* + for ( int i=0; i<6; ++i) + { + Fvector4 TransformedPlane; + ClipTransform.transform(TransformedPlane, UnitClipPlanes[i]); + TransformedPlane.normalize_as_plane(); + RCache.set_ca(strOOBBClipPlane, i, TransformedPlane); + } + */ + + /* + // Transform frustum to clip space + Fmatrix PlaneTransform; + PlaneTransform.transpose(Device.mInvFullTransform); + HW.pDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0x3F); + + for ( int i=0; i<6; ++i) + { + Fvector4 &ClipPlane = *(Fvector4*)&ClipFrustum.planes[i].n.x; + Fvector4 TransformedPlane; + PlaneTransform.transform(TransformedPlane, ClipPlane); + TransformedPlane.mul(-1.0f); + HW.pDevice->SetClipPlane( i, &TransformedPlane.x); + } + */ + } + + + /* + float clip[4]; + clip[0] = 1; + clip[1] = + clip[2] = + clip[3] = 0; + HW.pDevice->SetClipPlane( 0, clip); + */ + + + // Fetch4 : enable +// if (RImplementation.o.HW_smap_FETCH4) { + //. we hacked the shader to force smap on S0 +//# define FOURCC_GET4 MAKEFOURCC('G','E','T','4') +// HW.pDevice->SetSamplerState ( 0, D3DSAMP_MIPMAPLODBIAS, FOURCC_GET4 ); +// } + + RCache.set_ColorWriteEnable(D3DCOLORWRITEENABLE_RED|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_BLUE); + + RCache.set_Geometry(g_accum_volumetric); + //RCache.Render(D3DPT_TRIANGLELIST,0,0,VOLUMETRIC_SLICES*4,0,VOLUMETRIC_SLICES*2); + RCache.Render(D3DPT_TRIANGLELIST, 0, 0, iNumSlises * 4, 0, iNumSlises * 2); + + RCache.set_ColorWriteEnable(); + + // Fetch4 : disable +// if (RImplementation.o.HW_smap_FETCH4) { + //. we hacked the shader to force smap on S0 +//# define FOURCC_GET1 MAKEFOURCC('G','E','T','1') +// HW.pDevice->SetSamplerState ( 0, D3DSAMP_MIPMAPLODBIAS, FOURCC_GET1 ); +// } + + // Restore clip planes + //HW.pDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + RCache.set_ClipPlanes (FALSE,(Fmatrix *)0,0); + } +/* + // blend-copy + if (!RImplementation.o.fp16_blend) { + u_setrt (rt_Accumulator,NULL,NULL,HW.pBaseZB); + RCache.set_Element (s_accum_mask->E[SE_MASK_ACCUM_VOL] ); + RCache.set_c ("m_texgen", m_Texgen); + RCache.set_c ("m_texgen_J", m_Texgen_J ); + draw_volume (L); + } +*/ + //CHK_DX (HW.pDevice->SetRenderState(D3DRS_SCISSORTESTENABLE,FALSE)); + RCache.set_Scissor(0); +} \ No newline at end of file diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_spot_geom.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_spot_geom.cpp new file mode 100644 index 00000000000..dd75d199766 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_accum_spot_geom.cpp @@ -0,0 +1,188 @@ +#include "stdafx.h" + +#include "../xrRender/du_cone.h" +/* +Fvector du_cone_vertices[DU_CONE_NUMVERTEX]= +{ + 0.0000f, 0.0000f, 0.0000f, + 0.5000f, 0.0000f, 1.0000f, + 0.4619f, 0.1913f, 1.0000f, + 0.3536f, 0.3536f, 1.0000f, + 0.1913f, 0.4619f, 1.0000f, + -0.0000f, 0.5000f, 1.0000f, + -0.1913f, 0.4619f, 1.0000f, + -0.3536f, 0.3536f, 1.0000f, + -0.4619f, 0.1913f, 1.0000f, + -0.5000f, -0.0000f, 1.0000f, + -0.4619f, -0.1913f, 1.0000f, + -0.3536f, -0.3536f, 1.0000f, + -0.1913f, -0.4619f, 1.0000f, + 0.0000f, -0.5000f, 1.0000f, + 0.1913f, -0.4619f, 1.0000f, + 0.3536f, -0.3536f, 1.0000f, + 0.4619f, -0.1913f, 1.0000f, + 0.0000f, 0.0000f, 1.0000f+EPS_L +}; +u16 du_cone_faces[DU_CONE_NUMFACES*3]= +{ + 0, 2, 1, + 0, 3, 2, + 0, 4, 3, + 0, 5, 4, + 0, 6, 5, + 0, 7, 6, + 0, 8, 7, + 0, 9, 8, + 0, 10, 9, + 0, 11, 10, + 0, 12, 11, + 0, 13, 12, + 0, 14, 13, + 0, 15, 14, + 0, 16, 15, + 0, 1, 16, + 17, 1, 2, + 17, 2, 3, + 17, 3, 4, + 17, 4, 5, + 17, 5, 6, + 17, 6, 7, + 17, 7, 8, + 17, 8, 9, + 17, 9, 10, + 17,10, 11, + 17,11, 12, + 17,12, 13, + 17,13, 14, + 17,14, 15, + 17,15, 16, + 17,16, 1 +}; +*/ + +void CRenderTarget::accum_spot_geom_create () +{ + u32 dwUsage = GL_STATIC_DRAW; + + // vertices + { + u32 vCount = DU_CONE_NUMVERTEX; + u32 vSize = 3*4; + glGenBuffers(1, &g_accum_spot_vb); + glBindBuffer(GL_ARRAY_BUFFER, g_accum_spot_vb); + CHK_GL(glBufferData(GL_ARRAY_BUFFER, vCount*vSize, du_cone_vertices, dwUsage)); + } + + // Indices + { + u32 iCount = DU_CONE_NUMFACES*3; + glGenBuffers(1, &g_accum_spot_ib); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_accum_spot_ib); + CHK_GL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, iCount * 2, du_cone_faces, dwUsage)); + } +} + +void CRenderTarget::accum_spot_geom_destroy() +{ + glDeleteBuffers(1, &g_accum_spot_vb); + glDeleteBuffers(1, &g_accum_spot_ib); +} + +struct Slice +{ + Fvector m_Vert[4]; +}; + +void CRenderTarget::accum_volumetric_geom_create() +{ + u32 dwUsage = GL_STATIC_DRAW; + + // vertices + { + // VOLUMETRIC_SLICES quads + static const u32 vCount = VOLUMETRIC_SLICES * 4; + u32 vSize = 3 * 4; + //R_CHK (HW.pDevice->CreateVertexBuffer( + // vCount*vSize, + // dwUsage, + // 0, + // D3DPOOL_MANAGED, + // &g_accum_volumetric_vb, + // 0)); + //BYTE* pData = 0; + //R_CHK (g_accum_volumetric_vb->Lock(0,0,(void**)&pData,0)); + //Slice *pSlice = (Slice*)pData; + //float t=0; + //float dt = 1.0f/(VOLUMETRIC_SLICES-1); + //for ( int i=0; iCreateIndexBuffer(iCount*2,dwUsage,D3DFMT_INDEX16,D3DPOOL_MANAGED,&g_accum_volumetric_ib,0)); + //R_CHK (g_accum_volumetric_ib->Lock(0,0,(void**)&pData,0)); + //u16 *pInd = (u16*) pData; + //for ( u16 i=0; iUnlock (); + + BYTE Datap[iCount * 2]; + + u16 *pInd = (u16*)Datap; + for (u16 i = 0; iflags.type) { + case IRender_Light::REFLECTED : + case IRender_Light::POINT : + RCache.set_Geometry (g_accum_point); + RCache.Render (D3DPT_TRIANGLELIST,0,0,DU_SPHERE_NUMVERTEX,0,DU_SPHERE_NUMFACES); + break; + case IRender_Light::SPOT : + RCache.set_Geometry (g_accum_spot); + RCache.Render (D3DPT_TRIANGLELIST,0,0,DU_CONE_NUMVERTEX,0,DU_CONE_NUMFACES); + break; + case IRender_Light::OMNIPART : + RCache.set_Geometry (g_accum_omnipart); + RCache.Render (D3DPT_TRIANGLELIST,0,0,DU_SPHERE_PART_NUMVERTEX,0,DU_SPHERE_PART_NUMFACES); + break; + default: + break; + } +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_enable_scissor.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_enable_scissor.cpp new file mode 100644 index 00000000000..31b5497094b --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_enable_scissor.cpp @@ -0,0 +1,167 @@ +#include "stdafx.h" +#include "../../xrEngine/cl_intersect.h" +#include "../xrRender/du_cone.h" + +//extern Fvector du_cone_vertices [DU_CONE_NUMVERTEX]; + +BOOL tri_vs_sphere_intersect (Fvector& SC, float R, Fvector& v0, Fvector& v1, Fvector& v2) +{ + Fvector e0,e1; + return CDB::TestSphereTri (SC,R,v0,e0.sub(v1,v0),e1.sub(v2,v0)); +} + +void CRenderTarget::enable_dbt_bounds (light* L) +{ + if (!RImplementation.o.nvdbt) return; + if (!ps_r2_ls_flags.test(R2FLAG_USE_NVDBT)) return; + + u32 mask = 0xffffffff; + EFC_Visible vis = RImplementation.ViewBase.testSphere(L->spatial.sphere.P,L->spatial.sphere.R*1.01f,mask); + if (vis!=fcvFully) return; + + // xform BB + Fbox BB; + Fvector rr; rr.set(L->spatial.sphere.R,L->spatial.sphere.R,L->spatial.sphere.R); + BB.setb (L->spatial.sphere.P, rr); + + Fbox bbp; bbp.invalidate(); + for (u32 i=0; i<8; i++) { + Fvector pt; + BB.getpoint (i,pt); + Device.mFullTransform.transform (pt); + bbp.modify (pt); + } + u_DBT_enable (bbp.min.z,bbp.max.z); +} + +// nv-DBT +BOOL CRenderTarget::u_DBT_enable (float zMin, float zMax) +{ + if (!RImplementation.o.nvdbt) return FALSE; + if (!ps_r2_ls_flags.test(R2FLAG_USE_NVDBT)) return FALSE; + + return FALSE; + + // TODO: DX10: Check if DX10 supports this feature + // enable cheat + //HW.pDevice->SetRenderState(D3DRS_ADAPTIVETESS_X,MAKEFOURCC('N','V','D','B')); + //HW.pDevice->SetRenderState(D3DRS_ADAPTIVETESS_Z,*(DWORD*)&zMin); + //HW.pDevice->SetRenderState(D3DRS_ADAPTIVETESS_W,*(DWORD*)&zMax); + + //return TRUE; +} + +void CRenderTarget::u_DBT_disable () +{ + // TODO: DX10: Check if DX10 supports this feature + //if (RImplementation.o.nvdbt && ps_r2_ls_flags.test(R2FLAG_USE_NVDBT)) + // HW.pDevice->SetRenderState(D3DRS_ADAPTIVETESS_X,0); +} + +BOOL CRenderTarget::enable_scissor (light* L) // true if intersects near plane +{ + // Msg ("%d: %x type(%d), pos(%f,%f,%f)",Device.dwFrame,u32(L),u32(L->flags.type),VPUSH(L->position)); + + // Near plane intersection + BOOL near_intersect = FALSE; + { + Fmatrix& M = Device.mFullTransform; + Fvector4 plane; + plane.x = -(M._14 + M._13); + plane.y = -(M._24 + M._23); + plane.z = -(M._34 + M._33); + plane.w = -(M._44 + M._43); + float denom = -1.0f / _sqrt(_sqr(plane.x)+_sqr(plane.y)+_sqr(plane.z)); + plane.mul (denom); + Fplane P; P.n.set(plane.x,plane.y,plane.z); P.d = plane.w; + float p_dist = P.classify (L->spatial.sphere.P) - L->spatial.sphere.R; + near_intersect = (p_dist<=0); + } +#ifdef DEBUG + if (1) + { + Fsphere S; S.set (L->spatial.sphere.P,L->spatial.sphere.R); + dbg_spheres.push_back (mk_pair(S,L->color)); + } +#endif + + // Scissor + //. disable scissor because some bugs prevent it to work through multi-portals + //. if (!HW.Caps.bScissor) return near_intersect; + return near_intersect; + +#if 0 + CSector* S = (CSector*)L->spatial.sector; + _scissor bb = S->r_scissor_merged; + Irect R; + R.x1 = clampr (iFloor (bb.min.x*Device.dwWidth), int(0),int(Device.dwWidth)); + R.x2 = clampr (iCeil (bb.max.x*Device.dwWidth), int(0),int(Device.dwWidth)); + R.y1 = clampr (iFloor (bb.min.y*Device.dwHeight), int(0),int(Device.dwHeight)); + R.y2 = clampr (iCeil (bb.max.y*Device.dwHeight), int(0),int(Device.dwHeight)); + if ( (Device.dwWidth==u32(R.right - R.left)) && (Device.dwHeight==u32(R.bottom-R.top)) ) + { + // full-screen -> do nothing + } else { + // test if light-volume intersects scissor-rectangle + // if it does - do nothing, if doesn't - we look on light through portal + + // 1. convert rect into -1..1 space + Fbox2 b_pp = bb; + b_pp.min.x = b_pp.min.x * 2 - 1; + b_pp.max.x = b_pp.max.x * 2 - 1; + b_pp.min.y = (1-b_pp.min.y) * 2 - 1; + b_pp.max.y = (1-b_pp.max.y) * 2 - 1; + + // 2. construct scissor rectangle in post-projection space + Fvector3 s_points_pp [4]; + s_points_pp[0].set (bb.min.x,bb.min.y,bb.depth); // LT + s_points_pp[1].set (bb.max.x,bb.min.y,bb.depth); // RT + s_points_pp[2].set (bb.max.x,bb.max.y,bb.depth); // RB + s_points_pp[3].set (bb.min.x,bb.max.y,bb.depth); // LB + + // 3. convert it into world space + Fvector3 s_points [4]; + Fmatrix& iVP = Device.mInvFullTransform; + iVP.transform (s_points[0],s_points_pp[0]); + iVP.transform (s_points[1],s_points_pp[1]); + iVP.transform (s_points[2],s_points_pp[2]); + iVP.transform (s_points[3],s_points_pp[3]); + + // 4. check intersection of two triangles with (spatial, enclosing) sphere + BOOL bIntersect = tri_vs_sphere_intersect ( + L->spatial.sphere.P,L->spatial.sphere.R, + s_points[0],s_points[1],s_points[2] + ); + if (!bIntersect) bIntersect = tri_vs_sphere_intersect ( + L->spatial.sphere.P,L->spatial.sphere.R, + s_points[2],s_points[3],s_points[0] + ); + if (!bIntersect) { + // volume doesn't touch scissor - enable mask + RCache.set_Scissor(&R); + //CHK_DX (HW.pDevice->SetRenderState(D3DRS_SCISSORTESTENABLE,TRUE)); + //CHK_DX (HW.pDevice->SetScissorRect(&R)); + } else { + // __asm int 3; + RCache.set_Scissor(NULL); + } + } + + return near_intersect; +#endif +} +/* +{ + Fmatrix& M = RCache.xforms.m_wvp; + BOOL bIntersect = FALSE; + for (u32 vit=0; vitget_Width ())*param_noise_scale+EPS_S); + u32 th = iCeil(float(T->get_Height ())*param_noise_scale+EPS_S); + VERIFY2 (tw && th, "Noise scale can't be zero in any way"); + + // calculate shift from FPSes + im_noise_time -= Device.fTimeDelta; + if (im_noise_time<0) { + im_noise_shift_w = ::Random.randI(tw?tw:1); + im_noise_shift_h = ::Random.randI(th?th:1); + float fps_time = 1/param_noise_fps; + while (im_noise_time<0) im_noise_time += fps_time; + } + + u32 shift_w = im_noise_shift_w; + u32 shift_h = im_noise_shift_h; + float start_u = (float(shift_w)+.5f)/(tw); + float start_v = (float(shift_h)+.5f)/(th); + u32 _w = Device.dwWidth; + u32 _h = Device.dwHeight; + u32 cnt_w = _w / tw; + u32 cnt_h = _h / th; + float end_u = start_u + float(cnt_w) + 1; + float end_v = start_v + float(cnt_h) + 1; + + p0.set (start_u, start_v ); + p1.set (end_u, end_v ); +} + +void CRenderTarget::u_calc_tc_duality_ss (Fvector2& r0, Fvector2& r1, Fvector2& l0, Fvector2& l1) +{ + // Calculate ordinaty TCs from blur and SS + float tw = float(dwWidth); + float th = float(dwHeight); + if (dwHeight!=Device.dwHeight) param_blur = 1.f; + Fvector2 shift,p0,p1; + shift.set (.5f/tw, .5f/th); + shift.mul (param_blur); + p0.set (.5f/tw, .5f/th).add (shift); + p1.set ((tw+.5f)/tw, (th+.5f)/th ).add (shift); + + // Calculate Duality TC + float shift_u = param_duality_h*.5f; + float shift_v = param_duality_v*.5f; + + r0.set(p0.x,p0.y); r1.set(p1.x-shift_u,p1.y-shift_v); + l0.set(p0.x+shift_u,p0.y+shift_v); l1.set(p1.x,p1.y); +} + +BOOL CRenderTarget::u_need_PP () +{ + bool _blur = (param_blur>0.001f); + bool _gray = (param_gray>0.001f); + bool _noise = (param_noise>0.001f); + bool _dual = (param_duality_h>0.001f)||(param_duality_v>0.001f); + + // bool _menu_pp= g_pGamePersistent?g_pGamePersistent->OnRenderPPUI_query():false; + + bool _cbase = false; + { + int _r = color_get_R(param_color_base) ; _r=_abs(_r-int(0x7f)); + int _g = color_get_G(param_color_base) ; _g=_abs(_g-int(0x7f)); + int _b = color_get_B(param_color_base) ; _b=_abs(_b-int(0x7f)); + if (_r>2 || _g>2 || _b>2) _cbase = true ; + } + bool _cadd = false; + { + //int _r = color_get_R(param_color_add) ; + //int _g = color_get_G(param_color_add) ; + //int _b = color_get_B(param_color_add) ; + //if (_r>2 || _g>2 || _b>2) _cadd = true ; + int _r = _abs((int)(param_color_add.x*255)); + int _g = _abs((int)(param_color_add.y*255)); + int _b = _abs((int)(param_color_add.z*255)); + if (_r>2 || _g>2 || _b>2) _cadd = true ; + } + return _blur || _gray || _noise || _dual || _cbase || _cadd; +} + +struct TL_2c3uv { + Fvector4 p ; + u32 color0 ; + u32 color1 ; + Fvector2 uv [3] ; + IC void set (float x, float y, u32 c0, u32 c1, float u0, float v0, float u1, float v1, float u2, float v2) { + p.set (x,y,EPS_S,1.f); + color0 = c0; + color1 = c1; + uv[0].set(u0,v0); + uv[1].set(u1,v1); + uv[2].set(u2,v2); + } +}; + +void CRenderTarget::phase_pp () +{ + // combination/postprocess + u_setbb(); + RCache.set_Shader (s_postprocess ); + + int gblend = clampr (iFloor((1-param_gray)*255.f),0,255); + int nblend = clampr (iFloor((1-param_noise)*255.f),0,255); + u32 p_color = subst_alpha (param_color_base,nblend); + u32 p_gray = subst_alpha (param_color_gray,gblend); + Fvector p_brightness = param_color_add ; + // Msg ("param_gray:%f(%d),param_noise:%f(%d)",param_gray,gblend,param_noise,nblend); + // Msg ("base: %d,%d,%d", color_get_R(p_color), color_get_G(p_color), color_get_B(p_color)); + // Msg ("gray: %d,%d,%d", color_get_R(p_gray), color_get_G(p_gray), color_get_B(p_gray)); + // Msg ("add: %d,%d,%d", color_get_R(p_brightness), color_get_G(p_brightness), color_get_B(p_brightness)); + + // Draw full-screen quad textured with our scene image + u32 Offset; + float _w = float(Device.dwWidth); + float _h = float(Device.dwHeight); + + Fvector2 n0,n1,r0,r1,l0,l1; + u_calc_tc_duality_ss (r0,r1,l0,l1); + u_calc_tc_noise (n0,n1); + + // Fill vertex buffer + float du = ps_r1_pps_u, dv = ps_r1_pps_v; + TL_2c3uv* pv = (TL_2c3uv*) RCache.Vertex.Lock (4,g_postprocess.stride(),Offset); + pv->set(du+0, dv+0, p_color, p_gray, r0.x, r0.y, l0.x, l0.y, n0.x, n0.y); pv++; + pv->set(du+0, dv+float(_h), p_color, p_gray, r0.x, r1.y, l0.x, l1.y, n0.x, n1.y); pv++; + pv->set(du+float(_w), dv+0, p_color, p_gray, r1.x, r0.y, l1.x, l0.y, n1.x, n0.y); pv++; + pv->set(du+float(_w), dv+float(_h), p_color, p_gray, r1.x, r1.y, l1.x, l1.y, n1.x, n1.y); pv++; + RCache.Vertex.Unlock (4,g_postprocess.stride()); + + // Actual rendering + static shared_str s_brightness = "c_brightness"; + RCache.set_c ( s_brightness, p_brightness.x, p_brightness.y, p_brightness.z, 0 ); + RCache.set_Geometry (g_postprocess); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_accumulator.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_accumulator.cpp new file mode 100644 index 00000000000..4a41b113e98 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_accumulator.cpp @@ -0,0 +1,61 @@ +#include "stdafx.h" + +void CRenderTarget::phase_accumulator() +{ + // Targets + if (dwAccumulatorClearMark==Device.dwFrame) { + // normal operation - setup + if (RImplementation.o.fp16_blend) u_setrt(rt_Accumulator, NULL, NULL, HW.pBaseZB); + else u_setrt(rt_Accumulator_temp, NULL, NULL, HW.pBaseZB); + } else { + // initial setup + dwAccumulatorClearMark = Device.dwFrame; + + // clear + u_setrt(rt_Accumulator, NULL, NULL, HW.pBaseZB); + //dwLightMarkerID = 5; // start from 5, increment in 2 units + reset_light_marker(); + u32 clr4clear = color_rgba(0,0,0,0); // 0x00 + CHK_DX (HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_TARGET, clr4clear, 1.0f, 0L)); + + // render this after sun to avoid troubles with sun + /* + // Render emissive geometry, stencil - write 0x0 at pixel pos + RCache.set_xform_project (Device.mProject); + RCache.set_xform_view (Device.mView); + // Stencil - write 0x1 at pixel pos - + RCache.set_Stencil ( TRUE,D3DCMP_ALWAYS,0x01,0xff,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE,D3DSTENCILOP_KEEP); + //RCache.set_Stencil (TRUE,D3DCMP_ALWAYS,0x00,0xff,0xff,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE,D3DSTENCILOP_KEEP); + RCache.set_CullMode (CULL_CCW); + RCache.set_ColorWriteEnable (); + RImplementation.r_dsgraph_render_emissive (); + */ + // Stencil - draw only where stencil >= 0x1 + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); + RCache.set_CullMode (CULL_NONE); + RCache.set_ColorWriteEnable (); + + } + + // Restore viewport after shadow map rendering + RImplementation.rmNormal(); +} + +void CRenderTarget::phase_vol_accumulator() +{ + if (!m_bHasActiveVolumetric) + { + m_bHasActiveVolumetric = true; + u_setrt (rt_Generic_2, NULL,NULL,HW.pBaseZB); + u32 clr4clearVol = color_rgba(0,0,0,0); // 0x00 + CHK_DX (HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_TARGET, clr4clearVol, 1.0f, 0L)); + } + else + { + u_setrt (rt_Generic_2, NULL,NULL,HW.pBaseZB); + } + + RCache.set_Stencil (FALSE); + RCache.set_CullMode (CULL_NONE); + RCache.set_ColorWriteEnable (); +} \ No newline at end of file diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_bloom.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_bloom.cpp new file mode 100644 index 00000000000..b62fd07577b --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_bloom.cpp @@ -0,0 +1,328 @@ +#include "stdafx.h" + +#include "../../xrEngine/igame_persistent.h" +#include "../../xrEngine/environment.h" + +#pragma pack(push,4) +struct v_build { + Fvector4 p; + Fvector2 uv0; + Fvector2 uv1; + Fvector2 uv2; + Fvector2 uv3; +}; + +struct v_filter { + Fvector4 p; + Fvector4 uv0; + Fvector4 uv1; + Fvector4 uv2; + Fvector4 uv3; + Fvector4 uv4; + Fvector4 uv5; + Fvector4 uv6; + Fvector4 uv7; +}; +#pragma pack(pop) + +// Gauss filtering coeffs +// Samples: 0-central, -1, -2,..., -7, 1, 2,... 7 +// +void CalcGauss_k7( + Fvector4& w0, // weight + Fvector4& w1, // weight + float r =3.3f, // gaussian radius + float s_out =1.f // resulting magnitude + ) +{ + float W[8]; + + // calculate + float mag = 0; + for (int i=-7; i<=0; i++) W[-i] = expf (-float(i*i)/(2*r*r)); // weight + for (i=0; i<8; i++) mag += i?2*W[i]:W[i]; // symmetrical weight + for (i=0; i<8; i++) W[i] = s_out*W[i]/mag; + + // W[0]=0, W[7]=-7 + w0.set (W[1],W[2],W[3],W[4]); // -1, -2, -3, -4 + w1.set (W[5],W[6],W[7],W[0]); // -5, -6, -7, 0 +} +void CalcGauss_wave( + Fvector4& w0, // weight + Fvector4& w1, // weight + float r_base =3.3f, // gaussian radius + float r_detail =1.0f, // gaussian radius + float s_out =1.f // resulting magnitude + ) +{ + Fvector4 t0,t1; + CalcGauss_k7(w0,w1,r_base, s_out); + CalcGauss_k7(t0,t1,r_detail,s_out); + w0.add (t0); + w1.add (t1); +} + +void CRenderTarget::phase_bloom () +{ + u32 Offset; + + // Targets + u_setrt ( rt_Bloom_1,NULL,NULL,NULL ); // No need for ZBuffer at all + //RImplementation.rmNormal(); + + // Clear - don't clear - it's stupid here :) + // Stencil - disable + // Misc - draw everything (no culling) + //CHK_DX (HW.pDevice->SetRenderState ( D3DRS_ZENABLE, FALSE )); + RCache.set_Z(FALSE); + + // Transfer into Bloom1 + { + float _w = float(Device.dwWidth); + float _h = float(Device.dwHeight); + float _2w = _w/2; float tw = BLOOM_size_X; + float _2h = _h/2; float th = BLOOM_size_Y; + float _aspect_w = _2w/tw; + float _aspect_h = _2h/th; + Fvector2 one = { 1.f/_w, 1.f/_h }; one.x*=_aspect_w; one.y*=_aspect_h; + Fvector2 half = { .5f/_w, .5f/_h }; + Fvector2 a_0 = { half.x + 0, half.y + 0 }; + Fvector2 a_1 = { half.x + one.x, half.y + 0 }; + Fvector2 a_2 = { half.x + 0, half.y + one.y }; + Fvector2 a_3 = { half.x + one.x, half.y + one.y }; + Fvector2 b_0 = { 1 + a_0.x, 1 + a_0.y }; + Fvector2 b_1 = { 1 + a_1.x, 1 + a_1.y }; + Fvector2 b_2 = { 1 + a_2.x, 1 + a_2.y }; + Fvector2 b_3 = { 1 + a_3.x, 1 + a_3.y }; + + // Fill vertex buffer + v_build* pv = (v_build*) RCache.Vertex.Lock (4,g_bloom_build->vb_stride,Offset); + pv->p.set (EPS, EPS, EPS,1.f); + pv->uv0.set (a_0.x,a_0.y); pv->uv1.set (a_1.x,a_1.y); pv->uv2.set (a_2.x,a_2.y); pv->uv3.set (a_3.x,a_3.y); + pv++; + pv->p.set (EPS, float(th+EPS), EPS,1.f); + pv->uv0.set (a_0.x,b_0.y); pv->uv1.set (a_1.x,b_1.y); pv->uv2.set (a_2.x,b_2.y); pv->uv3.set (a_3.x,b_3.y); + pv++; + pv->p.set (float(tw+EPS),EPS, EPS,1.f); + pv->uv0.set (b_0.x,a_0.y); pv->uv1.set (b_1.x,a_1.y); pv->uv2.set (b_2.x,a_2.y); pv->uv3.set (b_3.x,a_3.y); + pv++; + pv->p.set (float(tw+EPS),float(th+EPS), EPS,1.f); + pv->uv0.set (b_0.x,b_0.y); pv->uv1.set (b_1.x,b_1.y); pv->uv2.set (b_2.x,b_2.y); pv->uv3.set (b_3.x,b_3.y); + pv++; + RCache.Vertex.Unlock (4,g_bloom_build->vb_stride); + + // Perform combine (all scalers must account for 4 samples + final diffuse multiply); + float s = ps_r2_ls_bloom_threshold; // scale + f_bloom_factor = .9f*f_bloom_factor + .1f*ps_r2_ls_bloom_speed*Device.fTimeDelta; // speed + RCache.set_Element (s_bloom->E[0]); + RCache.set_c ("b_params", s,s,s, f_bloom_factor); + RCache.set_Geometry (g_bloom_build ); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + + // Capture luminance values + phase_luminance ( ); + + if (ps_r2_ls_flags.test(R2FLAG_FASTBLOOM)) + { + // FAST FILTER + float _w = BLOOM_size_X; + float _h = BLOOM_size_Y; + float ddw = (1.f/_w)*ps_r2_ls_bloom_kernel_b; + float ddh = (1.f/_h)*ps_r2_ls_bloom_kernel_b; + Fvector2 p0; p0.set (.5f/_w, .5f/_h); + Fvector2 p1; p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + + v_build* pv = (v_build*) RCache.Vertex.Lock (4,g_bloom_build->vb_stride,Offset); + pv->p.set(EPS, EPS, EPS,1.f); pv->uv0.set(p0.x-ddw,p0.y-ddh);pv->uv1.set(p0.x+ddw,p0.y+ddh);pv->uv2.set(p0.x+ddw,p0.y-ddh);pv->uv3.set(p0.x-ddw,p0.y+ddh);pv++; + pv->p.set(EPS, float(_h+EPS), EPS,1.f); pv->uv0.set(p0.x-ddw,p1.y-ddh);pv->uv1.set(p0.x+ddw,p1.y+ddh);pv->uv2.set(p0.x+ddw,p1.y-ddh);pv->uv3.set(p0.x-ddw,p1.y+ddh);pv++; + pv->p.set(float(_w+EPS),EPS, EPS,1.f); pv->uv0.set(p1.x-ddw,p0.y-ddh);pv->uv1.set(p1.x+ddw,p0.y+ddh);pv->uv2.set(p1.x+ddw,p0.y-ddh);pv->uv3.set(p1.x-ddw,p0.y+ddh);pv++; + pv->p.set(float(_w+EPS),float(_h+EPS), EPS,1.f); pv->uv0.set(p1.x-ddw,p1.y-ddh);pv->uv1.set(p1.x+ddw,p1.y+ddh);pv->uv2.set(p1.x+ddw,p1.y-ddh);pv->uv3.set(p1.x-ddw,p1.y+ddh);pv++; + RCache.Vertex.Unlock (4,g_bloom_build->vb_stride); + RCache.set_Geometry (g_bloom_build); + + // P0 + u_setrt (rt_Bloom_2,NULL,NULL,NULL); // No need for ZBuffer at all + RCache.set_Element (s_bloom->E[3]); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + + // P1 + u_setrt (rt_Bloom_1,NULL,NULL,NULL); // No need for ZBuffer at all + RCache.set_Element (s_bloom->E[4]); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } else { + // SLOW FILTER + // Transfer into Bloom2, horizontal filter + { + float _w = BLOOM_size_X; + float _h = BLOOM_size_Y; + Fvector2 two = { 2.f/_w, 2.f/_h }; + Fvector2 one = { 1.f/_w, 1.f/_h }; + Fvector2 half = { .5f/_w, .5f/_h }; + Fvector4 a_0 = { half.x, half.y, half.y, half.x }; // center + Fvector4 a_1 = { a_0.x - one.x - half.x, half.y, half.y, a_0.w + one.x + half.x }; // -1,+1i + Fvector4 a_2 = { a_1.x - two.x, half.y, half.y, a_1.w + two.x }; // -2,+2i + Fvector4 a_3 = { a_2.x - two.x, half.y, half.y, a_2.w + two.x }; // -3,+3i + Fvector4 a_4 = { a_3.x - two.x, half.y, half.y, a_3.w + two.x }; // -4,+4i + Fvector4 a_5 = { a_4.x - two.x, half.y, half.y, a_4.w + two.x }; // -5,+5i + Fvector4 a_6 = { a_5.x - two.x, half.y, half.y, a_5.w + two.x }; // -6,+6i + Fvector4 a_7 = { a_6.x - two.x, half.y, half.y, a_6.w + two.x }; // -7,+7i + + // Fill vertex buffer + v_filter* pv = (v_filter*) RCache.Vertex.Lock (4,g_bloom_filter->vb_stride,Offset); + + // 1 - LT + pv->p.set (EPS, EPS, EPS,1.f); + pv->uv0.set (a_0.x,a_0.y,0,0); + pv->uv1.set (a_1.x,a_1.y,a_1.z,a_1.w); + pv->uv2.set (a_2.x,a_2.y,a_2.z,a_2.w); + pv->uv3.set (a_3.x,a_3.y,a_3.z,a_3.w); + pv->uv4.set (a_4.x,a_4.y,a_4.z,a_4.w); + pv->uv5.set (a_5.x,a_5.y,a_5.z,a_5.w); + pv->uv6.set (a_6.x,a_6.y,a_6.z,a_6.w); + pv->uv7.set (a_7.x,a_7.y,a_7.z,a_7.w); + pv++; + + // 0 - LB + pv->p.set (EPS, float(_h+EPS), EPS,1.f); + pv->uv0.set (a_0.x,1+a_0.y,0,0); + pv->uv1.set (a_1.x,1+a_1.y,1+a_1.z,a_1.w); + pv->uv2.set (a_2.x,1+a_2.y,1+a_2.z,a_2.w); + pv->uv3.set (a_3.x,1+a_3.y,1+a_3.z,a_3.w); + pv->uv4.set (a_4.x,1+a_4.y,1+a_4.z,a_4.w); + pv->uv5.set (a_5.x,1+a_5.y,1+a_5.z,a_5.w); + pv->uv6.set (a_6.x,1+a_6.y,1+a_6.z,a_6.w); + pv->uv7.set (a_7.x,1+a_7.y,1+a_7.z,a_7.w); + pv++; + + // 3 - RT + pv->p.set (float(_w+EPS), EPS, EPS,1.f); + pv->uv0.set (1+a_0.x,a_0.y,0,0); + pv->uv1.set (1+a_1.x,a_1.y,a_1.z,1+a_1.w); + pv->uv2.set (1+a_2.x,a_2.y,a_2.z,1+a_2.w); + pv->uv3.set (1+a_3.x,a_3.y,a_3.z,1+a_3.w); + pv->uv4.set (1+a_4.x,a_4.y,a_4.z,1+a_4.w); + pv->uv5.set (1+a_5.x,a_5.y,a_5.z,1+a_5.w); + pv->uv6.set (1+a_6.x,a_6.y,a_6.z,1+a_6.w); + pv->uv7.set (1+a_7.x,a_7.y,a_7.z,1+a_7.w); + pv++; + + // 2 - RB + pv->p.set (float(_w+EPS), float(_h+EPS), EPS,1.f); + pv->uv0.set (1+a_0.x,1+a_0.y,0,0); + pv->uv1.set (1+a_1.x,1+a_1.y,1+a_1.z,1+a_1.w); + pv->uv2.set (1+a_2.x,1+a_2.y,1+a_2.z,1+a_2.w); + pv->uv3.set (1+a_3.x,1+a_3.y,1+a_3.z,1+a_3.w); + pv->uv4.set (1+a_4.x,1+a_4.y,1+a_4.z,1+a_4.w); + pv->uv5.set (1+a_5.x,1+a_5.y,1+a_5.z,1+a_5.w); + pv->uv6.set (1+a_6.x,1+a_6.y,1+a_6.z,1+a_6.w); + pv->uv7.set (1+a_7.x,1+a_7.y,1+a_7.z,1+a_7.w); + pv++; + RCache.Vertex.Unlock (4,g_bloom_filter->vb_stride); + + // Perform filtering + Fvector4 w0,w1; + float kernel = ps_r2_ls_bloom_kernel_g; + CalcGauss_wave (w0,w1,kernel,kernel/3.f,ps_r2_ls_bloom_kernel_scale); + u_setrt (rt_Bloom_2,NULL,NULL,NULL); // No need for ZBuffer at all + RCache.set_Element (s_bloom->E[1]); + RCache.set_ca ("weight", 0, w0); + RCache.set_ca ("weight", 1, w1); + RCache.set_Geometry (g_bloom_filter); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + + // Transfer into Bloom1, vertical filter + { + float _w = BLOOM_size_X; + float _h = BLOOM_size_Y; + Fvector2 two = { 2.f/_w, 2.f/_h }; + Fvector2 one = { 1.f/_w, 1.f/_h }; + Fvector2 half = { .5f/_w, .5f/_h }; + Fvector4 a_0 = { half.x, half.y, half.y, half.x }; // center + Fvector4 a_1 = { half.x, a_0.y - one.y - half.y, half.y + one.y + a_0.z, half.x }; // -1,+1i + Fvector4 a_2 = { half.x, a_1.y - two.y, two.y + a_1.z, half.x }; // -2,+2i + Fvector4 a_3 = { half.x, a_2.y - two.y, two.y + a_2.z, half.x }; // -3,+3i + Fvector4 a_4 = { half.x, a_3.y - two.y, two.y + a_3.z, half.x }; // -4,+4i + Fvector4 a_5 = { half.x, a_4.y - two.y, two.y + a_4.z, half.x }; // -5,+5i + Fvector4 a_6 = { half.x, a_5.y - two.y, two.y + a_5.z, half.x }; // -6,+6i + Fvector4 a_7 = { half.x, a_6.y - two.y, two.y + a_6.z, half.x }; // -7,+7i + + // Fill vertex buffer + v_filter* pv = (v_filter*) RCache.Vertex.Lock (4,g_bloom_filter->vb_stride,Offset); + + // 1 - LT + pv->p.set (EPS, EPS, EPS,1.f); + pv->uv0.set (a_0.x,a_0.y,0,0); + pv->uv1.set (a_1.x,a_1.y,a_1.z,a_1.w); + pv->uv2.set (a_2.x,a_2.y,a_2.z,a_2.w); + pv->uv3.set (a_3.x,a_3.y,a_3.z,a_3.w); + pv->uv4.set (a_4.x,a_4.y,a_4.z,a_4.w); + pv->uv5.set (a_5.x,a_5.y,a_5.z,a_5.w); + pv->uv6.set (a_6.x,a_6.y,a_6.z,a_6.w); + pv->uv7.set (a_7.x,a_7.y,a_7.z,a_7.w); + pv++; + + // 0 - LB + pv->p.set (EPS, float(_h+EPS), EPS,1.f); + pv->uv0.set (a_0.x,1+a_0.y,0,0); + pv->uv1.set (a_1.x,1+a_1.y,1+a_1.z,a_1.w); + pv->uv2.set (a_2.x,1+a_2.y,1+a_2.z,a_2.w); + pv->uv3.set (a_3.x,1+a_3.y,1+a_3.z,a_3.w); + pv->uv4.set (a_4.x,1+a_4.y,1+a_4.z,a_4.w); + pv->uv5.set (a_5.x,1+a_5.y,1+a_5.z,a_5.w); + pv->uv6.set (a_6.x,1+a_6.y,1+a_6.z,a_6.w); + pv->uv7.set (a_7.x,1+a_7.y,1+a_7.z,a_7.w); + pv++; + + // 3 - RT + pv->p.set (float(_w+EPS), EPS, EPS,1.f); + pv->uv0.set (1+a_0.x,a_0.y,0,0); + pv->uv1.set (1+a_1.x,a_1.y,a_1.z,1+a_1.w); + pv->uv2.set (1+a_2.x,a_2.y,a_2.z,1+a_2.w); + pv->uv3.set (1+a_3.x,a_3.y,a_3.z,1+a_3.w); + pv->uv4.set (1+a_4.x,a_4.y,a_4.z,1+a_4.w); + pv->uv5.set (1+a_5.x,a_5.y,a_5.z,1+a_5.w); + pv->uv6.set (1+a_6.x,a_6.y,a_6.z,1+a_6.w); + pv->uv7.set (1+a_7.x,a_7.y,a_7.z,1+a_7.w); + pv++; + + // 2 - RB + pv->p.set (float(_w+EPS), float(_h+EPS), EPS,1.f); + pv->uv0.set (1+a_0.x,1+a_0.y,0,0); + pv->uv1.set (1+a_1.x,1+a_1.y,1+a_1.z,1+a_1.w); + pv->uv2.set (1+a_2.x,1+a_2.y,1+a_2.z,1+a_2.w); + pv->uv3.set (1+a_3.x,1+a_3.y,1+a_3.z,1+a_3.w); + pv->uv4.set (1+a_4.x,1+a_4.y,1+a_4.z,1+a_4.w); + pv->uv5.set (1+a_5.x,1+a_5.y,1+a_5.z,1+a_5.w); + pv->uv6.set (1+a_6.x,1+a_6.y,1+a_6.z,1+a_6.w); + pv->uv7.set (1+a_7.x,1+a_7.y,1+a_7.z,1+a_7.w); + pv++; + RCache.Vertex.Unlock (4,g_bloom_filter->vb_stride); + + // Perform filtering + Fvector4 w0,w1; + float kernel = ps_r2_ls_bloom_kernel_g * float(Device.dwHeight)/float(Device.dwWidth); + CalcGauss_wave (w0,w1,kernel,kernel/3.f,ps_r2_ls_bloom_kernel_scale); + u_setrt (rt_Bloom_1,NULL,NULL,NULL); // No need for ZBuffer at all + RCache.set_Element (s_bloom->E[2]); + RCache.set_ca ("weight", 0, w0); + RCache.set_ca ("weight", 1, w1); + RCache.set_Geometry (g_bloom_filter); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + } + + // we are left here with bloom-target setup as primary one + // for FP16-BLEND capable HW we can blend flares into smaller target, because they are smooth + //if (RImplementation.o.fp16_blend) g_pGamePersistent->Environment().RenderFlares (); // lens-flares + bool _menu_pp = g_pGamePersistent?g_pGamePersistent->OnRenderPPUI_query():false; + if (_menu_pp) + { + CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0L)); + }; + + // re-enable z-buffer + //CHK_DX (HW.pDevice->SetRenderState ( D3DRS_ZENABLE, TRUE )); + RCache.set_Z(TRUE); +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_combine.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_combine.cpp new file mode 100644 index 00000000000..5b7c8b0dfbb --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_combine.cpp @@ -0,0 +1,533 @@ +#include "stdafx.h" +#include "../../xrEngine/igame_persistent.h" +#include "../../xrEngine/environment.h" + +#include "glEnvironmentRender.h" + +#define STENCIL_CULL 0 + +void CRenderTarget::DoAsyncScreenshot() +{ + VERIFY(!"CRenderTarget::DoAsyncScreenshot() not implemented"); +} + +float hclip(float v, float dim) { return 2.f*v/dim - 1.f; } +void CRenderTarget::phase_combine () +{ + // TODO: DX10: Remove half poxel offset + bool _menu_pp = g_pGamePersistent?g_pGamePersistent->OnRenderPPUI_query():false; + + u32 Offset = 0; + Fvector2 p0,p1; + + //*** exposure-pipeline + u32 gpu_id = Device.dwFrame%HW.Caps.iGPUNum; + { + t_LUM_src->surface_set (GL_TEXTURE_2D, rt_LUM_pool[gpu_id*2+0]->pSurface); + t_LUM_dest->surface_set (GL_TEXTURE_2D, rt_LUM_pool[gpu_id*2+1]->pSurface); + } + + if (RImplementation.o.ssao_opt_data) + { + phase_downsamp(); + //phase_ssao(); + } + else if (RImplementation.o.ssao_blur_on) + phase_ssao(); + + // low/hi RTs + u_setrt ( rt_Generic_0,rt_Generic_1,0,HW.pBaseZB ); + CHK_DX(HW.pDevice->Clear(0L, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0L)); + RCache.set_CullMode ( CULL_NONE ); + RCache.set_Stencil ( FALSE ); + + BOOL split_the_scene_to_minimize_wait = FALSE; + if (ps_r2_ls_flags.test(R2FLAG_EXP_SPLIT_SCENE)) split_the_scene_to_minimize_wait=TRUE; + + // draw skybox + if (1) + { + // Moved to shader! + //RCache.set_ColorWriteEnable (); + // Moved to shader! + //RCache.set_Z(FALSE); + g_pGamePersistent->Environment().RenderSky (); + + // Igor: Render clouds before compine without Z-test + // to avoid siluets. HOwever, it's a bit slower process. + g_pGamePersistent->Environment().RenderClouds (); + + // Moved to shader! + //RCache.set_Z(TRUE); + } + + // + //if (RImplementation.o.bug) { + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); // stencil should be >= 1 + if (RImplementation.o.nvstencil) { + u_stencil_optimize (CRenderTarget::SO_Combine); + RCache.set_ColorWriteEnable (); + } + //} + + // calc m-blur matrices + Fmatrix m_previous, m_current; + Fvector2 m_blur_scale; + { + static Fmatrix m_saved_viewproj; + + // (new-camera) -> (world) -> (old_viewproj) + Fmatrix m_invview; m_invview.invert (Device.mView); + m_previous.mul (m_saved_viewproj,m_invview); + m_current.set (Device.mProject) ; + m_saved_viewproj.set(Device.mFullTransform) ; + float scale = ps_r2_mblur/2.f; + m_blur_scale.set (scale,-scale).div(12.f); + } + + // Draw full-screen quad textured with our scene image + if (!_menu_pp) + { + // Compute params + Fmatrix m_v2w; m_v2w.invert (Device.mView ); + CEnvDescriptorMixer& envdesc= *g_pGamePersistent->Environment().CurrentEnv ; + const float minamb = 0.001f; + Fvector4 ambclr = { _max(envdesc.ambient.x*2,minamb), _max(envdesc.ambient.y*2,minamb), _max(envdesc.ambient.z*2,minamb), 0 }; + ambclr.mul (ps_r2_sun_lumscale_amb); + +//. Fvector4 envclr = { envdesc.sky_color.x*2+EPS, envdesc.sky_color.y*2+EPS, envdesc.sky_color.z*2+EPS, envdesc.weight }; + Fvector4 envclr = { envdesc.hemi_color.x*2+EPS, envdesc.hemi_color.y*2+EPS, envdesc.hemi_color.z*2+EPS, envdesc.weight }; + + Fvector4 fogclr = { envdesc.fog_color.x, envdesc.fog_color.y, envdesc.fog_color.z, 0 }; + envclr.x *= 2*ps_r2_sun_lumscale_hemi; + envclr.y *= 2*ps_r2_sun_lumscale_hemi; + envclr.z *= 2*ps_r2_sun_lumscale_hemi; + Fvector4 sunclr,sundir; + + float fSSAONoise = 2.0f; + fSSAONoise *= tan(deg2rad(67.5f/2.0f)); + fSSAONoise /= tan(deg2rad(Device.fFOV/2.0f)); + + float fSSAOKernelSize = 150.0f; + fSSAOKernelSize *= tan(deg2rad(67.5f/2.0f)); + fSSAOKernelSize /= tan(deg2rad(Device.fFOV/2.0f)); + + + // sun-params + { + light* fuckingsun = (light*)RImplementation.Lights.sun_adapted._get() ; + Fvector L_dir,L_clr; float L_spec; + L_clr.set (fuckingsun->color.r,fuckingsun->color.g,fuckingsun->color.b); + L_spec = u_diffuse2s (L_clr); + Device.mView.transform_dir (L_dir,fuckingsun->direction); + L_dir.normalize (); + + sunclr.set (L_clr.x,L_clr.y,L_clr.z,L_spec); + sundir.set (L_dir.x,L_dir.y,L_dir.z,0); + } + + /* + // Fill VB + //float _w = float(Device.dwWidth); + //float _h = float(Device.dwHeight); + //p0.set (.5f/_w, .5f/_h); + //p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + //p0.set (.5f/_w, .5f/_h); + //p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + + // Fill vertex buffer + Fvector4* pv = (Fvector4*) RCache.Vertex.Lock (4,g_combine_VP->vb_stride,Offset); + //pv->set (hclip(EPS, _w), hclip(_h+EPS, _h), p0.x, p1.y); pv++; + //pv->set (hclip(EPS, _w), hclip(EPS, _h), p0.x, p0.y); pv++; + //pv->set (hclip(_w+EPS, _w), hclip(_h+EPS, _h), p1.x, p1.y); pv++; + //pv->set (hclip(_w+EPS, _w), hclip(EPS, _h), p1.x, p0.y); pv++; + pv->set (-1, 1, 0, 1); pv++; + pv->set (-1, -1, 0, 0); pv++; + pv->set (1, 1, 1, 1); pv++; + pv->set (1, -1, 1, 0); pv++; + RCache.Vertex.Unlock (4,g_combine_VP->vb_stride); + */ + + // Fill VB + float scale_X = float(Device.dwWidth) / float(TEX_jitter); + float scale_Y = float(Device.dwHeight)/ float(TEX_jitter); + + // Fill vertex buffer + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); + pv->set (-1, 1, 0, 0, 0, 0, 0 ); pv++; + pv->set (-1, -1, 0, 1, 0, 0, scale_Y ); pv++; + pv->set (1, 1, 1, 0, 0, scale_X, 0 ); pv++; + pv->set (1, -1, 1, 1, 0, scale_X, scale_Y ); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + + glEnvDescriptorMixerRender &envdescren = *(glEnvDescriptorMixerRender*)(&*envdesc.m_pDescriptorMixer); + + // Setup textures + GLuint e0 = _menu_pp?0:envdescren.sky_r_textures_env[0].second->surface_get(); + GLuint e1 = _menu_pp?0:envdescren.sky_r_textures_env[1].second->surface_get(); + t_envmap_0->surface_set (GL_TEXTURE_CUBE_MAP, e0); + t_envmap_1->surface_set (GL_TEXTURE_CUBE_MAP, e1); + + // Draw + RCache.set_Element (s_combine->E[0] ); + //RCache.set_Geometry (g_combine_VP ); + RCache.set_Geometry (g_combine ); + + RCache.set_c ("m_v2w", m_v2w ); + RCache.set_c ("L_ambient", ambclr ); + + RCache.set_c ("Ldynamic_color", sunclr ); + RCache.set_c ("Ldynamic_dir", sundir ); + + RCache.set_c ("env_color", envclr ); + RCache.set_c ("fog_color", fogclr ); + + RCache.set_c ("ssao_noise_tile_factor", fSSAONoise ); + RCache.set_c ("ssao_kernel_size", fSSAOKernelSize ); + + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + + // Forward rendering + { + u_setrt (rt_Generic_0,0,0,HW.pBaseZB); // LDR RT + RCache.set_CullMode (CULL_CCW); + RCache.set_Stencil (FALSE); + RCache.set_ColorWriteEnable (); + // TODO: DX10: CHeck this! + //g_pGamePersistent->Environment().RenderClouds (); + RImplementation.render_forward (); + if (g_pGamePersistent) g_pGamePersistent->OnRenderPPUI_main() ; // PP-UI + } + + // Igor: for volumetric lights + // combine light volume here + if (m_bHasActiveVolumetric) + phase_combine_volumetric(); + + // Perform blooming filter and distortion if needed + RCache.set_Stencil (FALSE); + + // for msaa we need a resolved color buffer - Holger + phase_bloom ( ); // HDR RT invalidated here + + //RImplementation.rmNormal(); + //u_setrt(rt_Generic_1,0,0,HW.pBaseZB); + + // Distortion filter + BOOL bDistort = RImplementation.o.distortion_enabled; // This can be modified + { + if ((0==RImplementation.mapDistort.size()) && !_menu_pp) + bDistort= FALSE; + if (bDistort) + { + u_setrt (rt_Generic_1,0,0,HW.pBaseZB); // Now RT is a distortion mask + RCache.set_CullMode (CULL_CCW); + RCache.set_Stencil (FALSE); + RCache.set_ColorWriteEnable (); + CHK_DX(HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_TARGET, color_rgba(127,127,0,127), 1.0f, 0L)); + RImplementation.r_dsgraph_render_distort (); + if (g_pGamePersistent) g_pGamePersistent->OnRenderPPUI_PP() ; // PP-UI + } + } + +/* + if( RImplementation.o.dx10_msaa ) + { + // we need to resolve rt_Generic_1 into rt_Generic_1_r + if( bDistort ) + HW.pDevice->ResolveSubresource( rt_Generic_1_r->pTexture->surface_get(), 0, rt_Generic_1->pTexture->surface_get(), 0, DXGI_FORMAT_R8G8B8A8_UNORM ); + } + */ + + // PP enabled ? + // Render to RT texture to be able to copy RT even in windowed mode. + // TODO: OGL: Implement screenshot functionality. + BOOL PP_Complex = u_need_PP();// | (BOOL)RImplementation.m_bMakeAsyncSS; + if (_menu_pp) PP_Complex = FALSE; + + // Combine everything + perform AA + if (PP_Complex) u_setrt ( rt_Color,0,0,HW.pBaseZB ); // LDR RT + else u_setbb (); + + //. u_setrt ( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB); + RCache.set_CullMode ( CULL_NONE ) ; + RCache.set_Stencil ( FALSE ) ; + + + if (1) + { + // + struct v_aa { + Fvector4 p; + Fvector2 uv0; + Fvector2 uv1; + Fvector2 uv2; + Fvector2 uv3; + Fvector2 uv4; + Fvector4 uv5; + Fvector4 uv6; + }; + + float _w = float(Device.dwWidth); + float _h = float(Device.dwHeight); + float ddw = 1.f/_w; + float ddh = 1.f/_h; + p0.set (.5f/_w, .5f/_h); + p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + + // Fill vertex buffer + v_aa* pv = (v_aa*) RCache.Vertex.Lock (4,g_aa_AA->vb_stride,Offset); + pv->p.set(EPS, EPS, EPS,1.f); pv->uv0.set(p0.x, p0.y);pv->uv1.set(p0.x-ddw,p0.y-ddh);pv->uv2.set(p0.x+ddw,p0.y+ddh);pv->uv3.set(p0.x+ddw,p0.y-ddh);pv->uv4.set(p0.x-ddw,p0.y+ddh);pv->uv5.set(p0.x-ddw,p0.y,p0.y,p0.x+ddw);pv->uv6.set(p0.x,p0.y-ddh,p0.y+ddh,p0.x);pv++; + pv->p.set(EPS, float(_h+EPS), EPS,1.f); pv->uv0.set(p0.x, p1.y);pv->uv1.set(p0.x-ddw,p1.y-ddh);pv->uv2.set(p0.x+ddw,p1.y+ddh);pv->uv3.set(p0.x+ddw,p1.y-ddh);pv->uv4.set(p0.x-ddw,p1.y+ddh);pv->uv5.set(p0.x-ddw,p1.y,p1.y,p0.x+ddw);pv->uv6.set(p0.x,p1.y-ddh,p1.y+ddh,p0.x);pv++; + pv->p.set(float(_w+EPS),EPS, EPS,1.f); pv->uv0.set(p1.x, p0.y);pv->uv1.set(p1.x-ddw,p0.y-ddh);pv->uv2.set(p1.x+ddw,p0.y+ddh);pv->uv3.set(p1.x+ddw,p0.y-ddh);pv->uv4.set(p1.x-ddw,p0.y+ddh);pv->uv5.set(p1.x-ddw,p0.y,p0.y,p1.x+ddw);pv->uv6.set(p1.x,p0.y-ddh,p0.y+ddh,p1.x);pv++; + pv->p.set(float(_w+EPS),float(_h+EPS), EPS,1.f); pv->uv0.set(p1.x, p1.y);pv->uv1.set(p1.x-ddw,p1.y-ddh);pv->uv2.set(p1.x+ddw,p1.y+ddh);pv->uv3.set(p1.x+ddw,p1.y-ddh);pv->uv4.set(p1.x-ddw,p1.y+ddh);pv->uv5.set(p1.x-ddw,p1.y,p1.y,p1.x+ddw);pv->uv6.set(p1.x,p1.y-ddh,p1.y+ddh,p1.x);pv++; + RCache.Vertex.Unlock (4,g_aa_AA->vb_stride); + + // Set up variable + Fvector2 vDofKernel; + vDofKernel.set(0.5f/Device.dwWidth, 0.5f/Device.dwHeight); + vDofKernel.mul(ps_r2_dof_kernel_size); + + // Draw COLOR + if (ps_r2_ls_flags.test(R2FLAG_AA)) RCache.set_Element (s_combine->E[bDistort?3:1]); // look at blender_combine.cpp + else RCache.set_Element (s_combine->E[bDistort?4:2]); // look at blender_combine.cpp + + RCache.set_c ("e_barrier", ps_r2_aa_barier.x, ps_r2_aa_barier.y, ps_r2_aa_barier.z, 0); + RCache.set_c ("e_weights", ps_r2_aa_weight.x, ps_r2_aa_weight.y, ps_r2_aa_weight.z, 0); + RCache.set_c ("e_kernel", ps_r2_aa_kernel, ps_r2_aa_kernel, ps_r2_aa_kernel, 0); + RCache.set_c ("m_current", m_current); + RCache.set_c ("m_previous", m_previous); + RCache.set_c ("m_blur", m_blur_scale.x,m_blur_scale.y, 0,0); + Fvector3 dof; + g_pGamePersistent->GetCurrentDof(dof); + RCache.set_c ("dof_params", dof.x, dof.y, dof.z, ps_r2_dof_sky); +//. RCache.set_c ("dof_params", ps_r2_dof.x, ps_r2_dof.y, ps_r2_dof.z, ps_r2_dof_sky); + RCache.set_c ("dof_kernel", vDofKernel.x, vDofKernel.y, ps_r2_dof_kernel_size, 0); + + RCache.set_Geometry (g_aa_AA); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + RCache.set_Stencil (FALSE); + + // if FP16-BLEND !not! supported - draw flares here, overwise they are already in the bloom target + /* if (!RImplementation.o.fp16_blend)*/ g_pGamePersistent->Environment().RenderFlares (); // lens-flares + + // PP-if required + if (PP_Complex) + { + phase_pp (); + } + + // Re-adapt luminance + RCache.set_Stencil (FALSE); + + //*** exposure-pipeline-clear + { + std::swap (rt_LUM_pool[gpu_id*2+0],rt_LUM_pool[gpu_id*2+1]); + t_LUM_src->surface_set (GL_TEXTURE_2D, NULL); + t_LUM_dest->surface_set (GL_TEXTURE_2D, NULL); + } + +#ifdef DEBUG + RCache.set_CullMode ( CULL_CCW ); + static xr_vector saved_dbg_planes; + if (bDebug) saved_dbg_planes= dbg_planes; + else dbg_planes = saved_dbg_planes; + if (1) for (u32 it=0; it.99f) L_dir.set(1,0,0); + L_right.crossproduct(L_up,L_dir); L_right.normalize (); + L_dir.crossproduct (L_right,L_up); L_dir.normalize (); + + Fvector p0,p1,p2,p3; + float sz = 100.f; + p0.mad (zero,L_right,sz).mad (L_dir,sz); + p1.mad (zero,L_right,sz).mad (L_dir,-sz); + p2.mad (zero,L_right,-sz).mad (L_dir,-sz); + p3.mad (zero,L_right,-sz).mad (L_dir,+sz); + RCache.dbg_DrawTRI (Fidentity,p0,p1,p2,0xffffffff); + RCache.dbg_DrawTRI (Fidentity,p2,p3,p0,0xffffffff); + } + + static xr_vector saved_dbg_lines; + if (bDebug) saved_dbg_lines = dbg_lines; + else dbg_lines = saved_dbg_lines; + if (1) for (u32 it=0; itvb_stride,Offset); + pv->set ((IX+0)*_w+EPS, (IY+1)*_h+EPS, EPS, 1.f, C, p0.x, p1.y); pv++; + pv->set ((IX+0)*_w+EPS, (IY+0)*_h+EPS, EPS, 1.f, C, p0.x, p0.y); pv++; + pv->set ((IX+1)*_w+EPS, (IY+1)*_h+EPS, EPS, 1.f, C, p1.x, p1.y); pv++; + pv->set ((IX+1)*_w+EPS, (IY+0)*_h+EPS, EPS, 1.f, C, p1.x, p0.y); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + + // Draw COLOR + RCache.set_Shader (s_combine_dbg_0); + RCache.set_Geometry (g_combine); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + + // Draw quater-screen quad textured with our accumulator + if (0) + { + u32 IX=1,IY=1; + p0.set (.5f/_w, .5f/_h); + p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + + // Fill vertex buffer + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); + pv->set ((IX+0)*_w+EPS, (IY+1)*_h+EPS, EPS, 1.f, C, p0.x, p1.y); pv++; + pv->set ((IX+0)*_w+EPS, (IY+0)*_h+EPS, EPS, 1.f, C, p0.x, p0.y); pv++; + pv->set ((IX+1)*_w+EPS, (IY+1)*_h+EPS, EPS, 1.f, C, p1.x, p1.y); pv++; + pv->set ((IX+1)*_w+EPS, (IY+0)*_h+EPS, EPS, 1.f, C, p1.x, p0.y); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + + // Draw COLOR + RCache.set_Shader (s_combine_dbg_1); + RCache.set_Geometry (g_combine); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + } + */ +#ifdef DEBUG + dbg_spheres.clear (); + dbg_lines.clear (); + dbg_planes.clear (); +#endif +} + +void CRenderTarget::phase_wallmarks () +{ + // Targets + RCache.set_RT(NULL,2); + RCache.set_RT(NULL,1); + u_setrt (rt_Color,NULL,NULL,HW.pBaseZB); + // Stencil - draw only where stencil >= 0x1 + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); + RCache.set_CullMode (CULL_CCW); + RCache.set_ColorWriteEnable (D3DCOLORWRITEENABLE_RED|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_BLUE); +} + +void CRenderTarget::phase_combine_volumetric() +{ + u32 Offset = 0; + //Fvector2 p0,p1; + + // TODO: DX10: Remove half pixel offset here + + //u_setrt(rt_Generic_0,0,0,HW.pBaseZB ); // LDR RT + u_setrt(rt_Generic_0,rt_Generic_1,0,HW.pBaseZB ); + // Sets limits to both render targets + RCache.set_ColorWriteEnable(D3DCOLORWRITEENABLE_RED|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_BLUE); + { + // Compute params + Fmatrix m_v2w; m_v2w.invert (Device.mView ); + CEnvDescriptorMixer& envdesc= *g_pGamePersistent->Environment().CurrentEnv ; + const float minamb = 0.001f; + Fvector4 ambclr = { _max(envdesc.ambient.x*2,minamb), _max(envdesc.ambient.y*2,minamb), _max(envdesc.ambient.z*2,minamb), 0 }; + ambclr.mul (ps_r2_sun_lumscale_amb); + +//. Fvector4 envclr = { envdesc.sky_color.x*2+EPS, envdesc.sky_color.y*2+EPS, envdesc.sky_color.z*2+EPS, envdesc.weight }; + Fvector4 envclr = { envdesc.hemi_color.x*2+EPS, envdesc.hemi_color.y*2+EPS, envdesc.hemi_color.z*2+EPS, envdesc.weight }; + + + Fvector4 fogclr = { envdesc.fog_color.x, envdesc.fog_color.y, envdesc.fog_color.z, 0 }; + envclr.x *= 2*ps_r2_sun_lumscale_hemi; + envclr.y *= 2*ps_r2_sun_lumscale_hemi; + envclr.z *= 2*ps_r2_sun_lumscale_hemi; + Fvector4 sunclr,sundir; + + // sun-params + { + light* fuckingsun = (light*)RImplementation.Lights.sun_adapted._get() ; + Fvector L_dir,L_clr; float L_spec; + L_clr.set (fuckingsun->color.r,fuckingsun->color.g,fuckingsun->color.b); + L_spec = u_diffuse2s (L_clr); + Device.mView.transform_dir (L_dir,fuckingsun->direction); + L_dir.normalize (); + + sunclr.set (L_clr.x,L_clr.y,L_clr.z,L_spec); + sundir.set (L_dir.x,L_dir.y,L_dir.z,0); + } + + // Fill VB + //float _w = float(Device.dwWidth); + //float _h = float(Device.dwHeight); + //p0.set (.5f/_w, .5f/_h); + //p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + + // Fill vertex buffer + //Fvector4* pv = (Fvector4*) RCache.Vertex.Lock (4,g_combine_VP->vb_stride,Offset); + //pv->set (hclip(EPS, _w), hclip(_h+EPS, _h), p0.x, p1.y); pv++; + //pv->set (hclip(EPS, _w), hclip(EPS, _h), p0.x, p0.y); pv++; + //pv->set (hclip(_w+EPS, _w), hclip(_h+EPS, _h), p1.x, p1.y); pv++; + //pv->set (hclip(_w+EPS, _w), hclip(EPS, _h), p1.x, p0.y); pv++; + //RCache.Vertex.Unlock (4,g_combine_VP->vb_stride); + + // Fill VB + float scale_X = float(Device.dwWidth) / float(TEX_jitter); + float scale_Y = float(Device.dwHeight)/ float(TEX_jitter); + + // Fill vertex buffer + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); + pv->set (-1, 1, 0, 0, 0, 0, 0 ); pv++; + pv->set (-1, -1, 0, 1, 0, 0, scale_Y ); pv++; + pv->set (1, 1, 1, 0, 0, scale_X, 0 ); pv++; + pv->set (1, -1, 1, 1, 0, scale_X, scale_Y ); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + + // Draw + RCache.set_Element (s_combine_volumetric->E[0] ); + //RCache.set_Geometry (g_combine_VP ); + RCache.set_Geometry (g_combine ); + + RCache.set_c ("m_v2w", m_v2w ); + RCache.set_c ("L_ambient", ambclr ); + + RCache.set_c ("Ldynamic_color", sunclr ); + RCache.set_c ("Ldynamic_dir", sundir ); + + RCache.set_c ("env_color", envclr ); + RCache.set_c ("fog_color", fogclr ); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + RCache.set_ColorWriteEnable(); +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_luminance.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_luminance.cpp new file mode 100644 index 00000000000..582c7acc5af --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_luminance.cpp @@ -0,0 +1,136 @@ +#include "stdafx.h" + +#pragma pack(push,4) +struct v_build { + Fvector4 p; + Fvector2 uv0; + Fvector2 uv1; + Fvector2 uv2; + Fvector2 uv3; +}; + +struct v_filter { + Fvector4 p; + Fvector4 uv[8]; +}; +#pragma pack(pop) + +void CRenderTarget::phase_luminance() +{ + u32 Offset = 0; +// float eps = EPS_S; + float eps = 0; + + // Targets + RCache.set_Stencil (FALSE); + RCache.set_CullMode (CULL_NONE); + RCache.set_ColorWriteEnable (); + RCache.set_Z(FALSE); + //CHK_DX (HW.pDevice->SetRenderState (D3DRS_ZENABLE,FALSE)); + + // 000: Perform LUM-SAT, pass 0, 256x256 => 64x64 + u_setrt (rt_LUM_64,NULL,NULL,NULL); + //RImplementation.rmNormal(); + { + float ts = 64; + float _w = float(BLOOM_size_X); + float _h = float(BLOOM_size_Y); + Fvector2 one = { 2.f/_w, 2.f/_h }; // two, infact + Fvector2 half = { 1.f/_w, 1.f/_h }; // one, infact + Fvector2 a_0 = { half.x + 0, half.y + 0 }; + Fvector2 a_1 = { half.x + one.x, half.y + 0 }; + Fvector2 a_2 = { half.x + 0, half.y + one.y }; + Fvector2 a_3 = { half.x + one.x, half.y + one.y }; + Fvector2 b_0 = { 1 + a_0.x, 1 + a_0.y }; + Fvector2 b_1 = { 1 + a_1.x, 1 + a_1.y }; + Fvector2 b_2 = { 1 + a_2.x, 1 + a_2.y }; + Fvector2 b_3 = { 1 + a_3.x, 1 + a_3.y }; + + // Fill vertex buffer + v_build* pv = (v_build*) RCache.Vertex.Lock (4,g_bloom_build->vb_stride,Offset); + pv->p.set (eps, eps, eps,1.f); pv->uv0.set (a_0.x,a_0.y); pv->uv1.set (a_1.x,a_1.y); pv->uv2.set (a_2.x,a_2.y); pv->uv3.set (a_3.x,a_3.y); pv++; + pv->p.set (eps, float(ts+eps), eps,1.f); pv->uv0.set (a_0.x,b_0.y); pv->uv1.set (a_1.x,b_1.y); pv->uv2.set (a_2.x,b_2.y); pv->uv3.set (a_3.x,b_3.y); pv++; + pv->p.set (float(ts+eps), eps, eps,1.f); pv->uv0.set (b_0.x,a_0.y); pv->uv1.set (b_1.x,a_1.y); pv->uv2.set (b_2.x,a_2.y); pv->uv3.set (b_3.x,a_3.y); pv++; + pv->p.set (float(ts+eps), float(ts+eps), eps,1.f); pv->uv0.set (b_0.x,b_0.y); pv->uv1.set (b_1.x,b_1.y); pv->uv2.set (b_2.x,b_2.y); pv->uv3.set (b_3.x,b_3.y); pv++; + RCache.Vertex.Unlock (4,g_bloom_build->vb_stride); + RCache.set_Element (s_luminance->E[0]); + RCache.set_Geometry (g_bloom_build ); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + + // 111: Perform LUM-SAT, pass 1, 64x64 => 8x8 + u_setrt (rt_LUM_8,NULL,NULL,NULL); + //RImplementation.rmNormal(); + { + // Build filter-kernel + float _ts = 8; + float _src = float(64); + Fvector2 a[16],b[16]; + for (int k=0; k<16; k++) { + int _x = (k*2+1)%8; // 1,3,5,7 + int _y = ((k/4)*2+1); // 1,1,1,1 ~ 3,3,3,3 ~...etc... + a[k].set(_x,_y).div (_src); + b[k].set(a[k]).add (1); + } + + // Fill vertex buffer + v_filter* pv = (v_filter*) RCache.Vertex.Lock (4,g_bloom_filter->vb_stride,Offset); + pv->p.set (eps, eps, eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(a[t].x,a[t].y, a[t+8].y,a[t+8].x); // xy/yx - left+up + pv++; + pv->p.set (eps, float(_ts+eps), eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(a[t].x,b[t].y, b[t+8].y,a[t+8].x); // xy/yx - left+down + pv++; + pv->p.set (float(_ts+eps),eps, eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(b[t].x,a[t].y, a[t+8].y,b[t+8].x); // xy/yx - right+up + pv++; + pv->p.set (float(_ts+eps),float(_ts+eps), eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(b[t].x,b[t].y, b[t+8].y,b[t+8].x); // xy/yx - right+down + pv++; + RCache.Vertex.Unlock (4,g_bloom_filter->vb_stride); + RCache.set_Element (s_luminance->E[1] ); + RCache.set_Geometry (g_bloom_filter ); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + + // 222: Perform LUM-SAT, pass 2, 8x8 => 1x1 + u32 gpu_id = Device.dwFrame%HW.Caps.iGPUNum; + u_setrt (rt_LUM_pool[gpu_id*2+1],NULL,NULL,NULL); + //RImplementation.rmNormal(); + { + // Build filter-kernel + float _ts = 1; + float _src = float(8); + Fvector2 a[16],b[16]; + for (int k=0; k<16; k++) { + int _x = (k*2+1)%8; // 1,3,5,7 + int _y = ((k/4)*2+1); // 1,1,1,1 ~ 3,3,3,3 ~...etc... + a[k].set(_x,_y).div (_src); + b[k].set(a[k]).add (1); + } + + // Fill vertex buffer + v_filter* pv = (v_filter*) RCache.Vertex.Lock (4,g_bloom_filter->vb_stride,Offset); + pv->p.set (eps, eps, eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(a[t].x,a[t].y, a[t+8].y,a[t+8].x); // xy/yx - left+up + pv++; + pv->p.set (eps, float(_ts+eps), eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(a[t].x,b[t].y, b[t+8].y,a[t+8].x); // xy/yx - left+down + pv++; + pv->p.set (float(_ts+eps),eps, eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(b[t].x,a[t].y, a[t+8].y,b[t+8].x); // xy/yx - right+up + pv++; + pv->p.set (float(_ts+eps),float(_ts+eps), eps,1.f); for (int t=0; t<8; t++) pv->uv[t].set(b[t].x,b[t].y, b[t+8].y,b[t+8].x); // xy/yx - right+down + pv++; + RCache.Vertex.Unlock (4,g_bloom_filter->vb_stride); + + f_luminance_adapt = .9f*f_luminance_adapt + .1f*Device.fTimeDelta*ps_r2_tonemap_adaptation; + float amount = ps_r2_ls_flags.test(R2FLAG_TONEMAP)?ps_r2_tonemap_amount:0; + Fvector3 _none, _full, _result; + _none.set (1, 0, 1 ); + _full.set (ps_r2_tonemap_middlegray, 1.f, ps_r2_tonemap_low_lum ); + _result.lerp (_none, _full, amount ); + + RCache.set_Element (s_luminance->E[2] ); + RCache.set_Geometry (g_bloom_filter ); + RCache.set_c("MiddleGray", _result.x,_result.y,_result.z,f_luminance_adapt ); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + + // Cleanup states + //CHK_DX (HW.pDevice->SetRenderState(D3DRS_ZENABLE,TRUE)); + RCache.set_Z(TRUE); +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_occq.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_occq.cpp new file mode 100644 index 00000000000..a9aa0c7794b --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_occq.cpp @@ -0,0 +1,10 @@ +#include "stdafx.h" + +void CRenderTarget::phase_occq () +{ + u_setrt ( Device.dwWidth,Device.dwHeight,NULL,NULL,NULL,HW.pBaseZB); + RCache.set_Shader ( s_occq ); + RCache.set_CullMode ( CULL_CCW ); + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); + RCache.set_ColorWriteEnable (FALSE ); +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_scene.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_scene.cpp new file mode 100644 index 00000000000..830c4438c51 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_scene.cpp @@ -0,0 +1,104 @@ +#include "stdafx.h" + +// startup +void CRenderTarget::phase_scene_prepare () +{ + // Clear depth & stencil + //u_setrt ( Device.dwWidth,Device.dwHeight,HW.pBaseRT,NULL,NULL,HW.pBaseZB ); + //CHK_DX ( HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x0, 1.0f, 0L) ); + // Igor: soft particles + + CEnvDescriptor& E = *g_pGamePersistent->Environment().CurrentEnv; + float fValue = E.m_fSunShaftsIntensity; + // TODO: add multiplication by sun color here + //if (fValue<0.0001) FlagSunShafts = 0; + + // TODO: DX10: Check if complete clear of _ALL_ rendertargets will increase + // FPS. Make check for SLI configuration. + if ( RImplementation.o.advancedpp && + ( + ps_r2_ls_flags.test(R2FLAG_SOFT_PARTICLES|R2FLAG_DOF) || + ( (ps_r_sun_shafts>0) && (fValue>=0.0001) ) || + (ps_r_ssao>0) + ) + ) + { + u_setrt ( Device.dwWidth,Device.dwHeight,rt_Position->pSurface,NULL,NULL,HW.pBaseZB ); + CHK_DX ( HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x0, 1.0f, 0L) ); + } + else + { + u_setrt ( Device.dwWidth,Device.dwHeight,NULL,NULL,NULL,HW.pBaseZB ); + CHK_DX ( HW.pDevice->Clear ( 0L, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x0, 1.0f, 0L) ); + } + + // Igor: for volumetric lights + m_bHasActiveVolumetric = false; + // Clear later if try to draw volumetric +} + +// begin +void CRenderTarget::phase_scene_begin () +{ + GLuint pZB = HW.pBaseZB; + + // Targets, use accumulator for temporary storage + if (RImplementation.o.albedo_wo) u_setrt (rt_Position, rt_Normal, rt_Accumulator, HW.pBaseZB); + else u_setrt (rt_Position, rt_Normal, rt_Color, HW.pBaseZB); + + // Stencil - write 0x1 at pixel pos + RCache.set_Stencil ( TRUE,D3DCMP_ALWAYS,0x01,0xff,0x7f,D3DSTENCILOP_KEEP,D3DSTENCILOP_REPLACE,D3DSTENCILOP_KEEP); + + // Misc - draw only front-faces + // TODO: DX10: siable two-sided stencil here + //CHK_DX(HW.pDevice->SetRenderState ( D3DRS_TWOSIDEDSTENCILMODE,FALSE )); + RCache.set_CullMode ( CULL_CCW ); + RCache.set_ColorWriteEnable ( ); +} + +void CRenderTarget::disable_aniso () +{ + // Disable ANISO + // TODO: DX10: disable aniso here + //for (u32 i=0; iSetSamplerState( i, D3DSAMP_MAXANISOTROPY, 1 )); +} + +// end +void CRenderTarget::phase_scene_end () +{ + disable_aniso (); + + if (!RImplementation.o.albedo_wo) return; + + // transfer from "rt_Accumulator" into "rt_Color" + u_setrt ( rt_Color, 0, 0, HW.pBaseZB ); + RCache.set_CullMode ( CULL_NONE ); + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); // stencil should be >= 1 + if (RImplementation.o.nvstencil) u_stencil_optimize (CRenderTarget::SO_Combine); + RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); // stencil should be >= 1 + RCache.set_ColorWriteEnable (); + + // common calc for quad-rendering + u32 Offset; + u32 C = color_rgba (255,255,255,255); + float _w = float (Device.dwWidth); + float _h = float (Device.dwHeight); + Fvector2 p0,p1; + p0.set (.5f/_w, .5f/_h); + p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + float d_Z = EPS_S, d_W = 1.f; + + // Fill vertex buffer + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); + pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p1.y); pv++; + pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p0.y); pv++; + pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p1.y); pv++; + pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p0.y); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + + // if (stencil>=1 && aref_pass) stencil = light_id + RCache.set_Element (s_accum_mask->E[SE_MASK_ALBEDO]); // masker + RCache.set_Geometry (g_combine); + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_smap_D.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_smap_D.cpp new file mode 100644 index 00000000000..7de8d07c13a --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_smap_D.cpp @@ -0,0 +1,64 @@ +#include "stdafx.h" + +void CRenderTarget::phase_smap_direct (light* L, u32 sub_phase) +{ + // TODO: DX10: Check thst we will never need old SMap implementation + // Targets + if (RImplementation.o.HW_smap) u_setrt (rt_smap_surf, NULL, NULL, rt_smap_depth->pSurface); + //else u_setrt (rt_smap_surf, NULL, NULL, rt_smap_ZB); + else VERIFY(!"Use HW SMap only for OGL!"); + + + // Don't have rect clear for OGL + // TODO: DX9: Full clear must be faster for the near phase for SLI + // inobody clears this buffer _this_ frame. + // Clear + //if (SE_SUN_NEAR==sub_phase) { + // optimized clear + // D3DRECT R; + // R.x1 = L->X.D.minX; + // R.x2 = L->X.D.maxX; + // R.y1 = L->X.D.minY; + // R.y2 = L->X.D.maxY; + // CHK_DX (HW.pDevice->Clear( 1L, &R, D3DCLEAR_ZBUFFER, 0xFFFFFFFF, 1.0f, 0L)); + //} else { + // full-clear + CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER, 0xFFFFFFFF, 1.0f, 0L)); + //} + + // Prepare viewport for shadow map rendering + if (sub_phase!=SE_SUN_RAIN_SMAP ) + RImplementation.rmNormal(); + else + { + //CHK_DX (HW.pDevice->SetViewport(&VP)); + glViewport(L->X.D.minX,L->X.D.minY, + (L->X.D.maxX - L->X.D.minX) , + (L->X.D.maxY - L->X.D.minY)); + } + + // Stencil - disable + RCache.set_Stencil ( FALSE ); + + // TODO: DX10: Implement culling reverse for DX10 + // Misc - draw only front/back-faces + /* + if (SE_SUN_NEAR==sub_phase) RCache.set_CullMode ( CULL_CCW ); // near + else { + if (RImplementation.o.HW_smap) RCache.set_CullMode ( CULL_CW ); // far, reversed + else RCache.set_CullMode ( CULL_CCW ); // far, front-faces + } + if (RImplementation.o.HW_smap) RCache.set_ColorWriteEnable ( FALSE ); + else RCache.set_ColorWriteEnable ( ); + */ +} + +void CRenderTarget::phase_smap_direct_tsh (light* L, u32 sub_phase) +{ + VERIFY (RImplementation.o.Tshadows); + u32 _clr = 0xffffffff; //color_rgba(127,127,12,12); + RCache.set_ColorWriteEnable (); + // Prepare viewport for shadow map rendering + RImplementation.rmNormal(); + CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, _clr, 1.0f, 0L)); +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_smap_S.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_smap_S.cpp new file mode 100644 index 00000000000..7593b8d04cc --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_smap_S.cpp @@ -0,0 +1,70 @@ +#include "stdafx.h" + +void CRenderTarget::phase_smap_spot_clear() +{ + // TODO: OGL: CHeck if we don't need old-style SMAP + if (RImplementation.o.HW_smap) u_setrt(rt_smap_surf, NULL, NULL, rt_smap_depth->pSurface); + //else u_setrt (rt_smap_surf, NULL, NULL, rt_smap_ZB); + else VERIFY(!"Use HW SMap only for OGL!"); + CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0L)); +} + +void CRenderTarget::phase_smap_spot (light* L) +{ + // Targets + viewport + // TODO: OGL: CHeck if we don't need old-style SMAP + if (RImplementation.o.HW_smap) u_setrt (rt_smap_surf, NULL, NULL, rt_smap_depth->pSurface); + //else u_setrt (rt_smap_surf, NULL, NULL, rt_smap_ZB); + else VERIFY(!"Use HW SMap only for OGL!"); + //CHK_DX (HW.pDevice->SetViewport(&VP)); + glViewport (L->X.S.posX,L->X.S.posY,L->X.S.size,L->X.S.size); + + // Misc - draw only front-faces //back-faces + RCache.set_CullMode ( CULL_CCW ); + RCache.set_Stencil ( FALSE ); + // no transparency + #pragma todo("can optimize for multi-lights covering more than say 50%...") + if (RImplementation.o.HW_smap) RCache.set_ColorWriteEnable (FALSE); + //CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0L)); + // Do it once per smap generation pass in phase_smap_spot_clear + //HW.pDevice->ClearDepthStencilView( rt_smap_depth->pZRT, D3D10_CLEAR_DEPTH, 1.0f, 0L); +} + +void CRenderTarget::phase_smap_spot_tsh (light* L) +{ + VERIFY(!"Implement clear of the buffer for tsh!"); + VERIFY (RImplementation.o.Tshadows); + RCache.set_ColorWriteEnable (); + if (IRender_Light::OMNIPART == L->flags.type) { + // omni-part + CHK_DX (HW.pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, 0xffffffff, 1.0f, 0L)); + } else { + // real-spot + // Select color-mask + ref_shader shader = L->s_spot; + if (!shader) shader = s_accum_spot; + RCache.set_Element (shader->E[ SE_L_FILL ] ); + + // Fill vertex buffer + Fvector2 p0,p1; + u32 Offset; + u32 C = color_rgba (255,255,255,255); + float _w = float(L->X.S.size); + float _h = float(L->X.S.size); + float d_Z = EPS_S; + float d_W = 1.f; + p0.set (.5f/_w, .5f/_h); + p1.set ((_w+.5f)/_w, (_h+.5f)/_h ); + + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); + pv->set (EPS, float(_h+EPS), d_Z, d_W, C, p0.x, p1.y); pv++; + pv->set (EPS, EPS, d_Z, d_W, C, p0.x, p0.y); pv++; + pv->set (float(_w+EPS), float(_h+EPS), d_Z, d_W, C, p1.x, p1.y); pv++; + pv->set (float(_w+EPS), EPS, d_Z, d_W, C, p1.x, p0.y); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + RCache.set_Geometry (g_combine); + + // draw + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } +} diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_ssao.cpp b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_ssao.cpp new file mode 100644 index 00000000000..9b29b88f6ea --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_phase_ssao.cpp @@ -0,0 +1,121 @@ +#include "stdafx.h" + +void CRenderTarget::phase_ssao () +{ + u32 Offset = 0; + + u_setrt(rt_ssao_temp, NULL, NULL, NULL); // No need for ZBuffer at all + u32 clr4clear = color_rgba(0, 0, 0, 0); // 0x00 + CHK_DX(HW.pDevice->Clear(0L, NULL, D3DCLEAR_TARGET, clr4clear, 1.0f, 0L)); + + // low/hi RTs + u_setrt ( rt_ssao_temp,0,0,0/*HW.pBaseZB*/ ); + RCache.set_Stencil (FALSE); + + /*RCache.set_Stencil (TRUE,D3DCMP_LESSEQUAL,0x01,0xff,0x00); // stencil should be >= 1 + if (RImplementation.o.nvstencil) { + u_stencil_optimize (CRenderTarget::SO_Combine); + RCache.set_ColorWriteEnable (); + }*/ + + // Compute params + Fmatrix m_v2w; m_v2w.invert (Device.mView ); + + float fSSAONoise = 2.0f; + fSSAONoise *= tan(deg2rad(67.5f)); + fSSAONoise /= tan(deg2rad(Device.fFOV)); + + float fSSAOKernelSize = 150.0f; + fSSAOKernelSize *= tan(deg2rad(67.5f)); + fSSAOKernelSize /= tan(deg2rad(Device.fFOV)); + + // Fill VB + float scale_X = float(Device.dwWidth) * 0.5f / float(TEX_jitter); + float scale_Y = float(Device.dwHeight) * 0.5f / float(TEX_jitter); + + float _w = float(Device.dwWidth) * 0.5f; + float _h = float(Device.dwHeight) * 0.5f; + + glViewport(0, 0, _w, _h); + + // Fill vertex buffer + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); + pv->set ( -1, 1, 0, 0, 0, 0, 0 ); pv++; + pv->set ( -1, -1, 0, 1, 0, 0, scale_Y ); pv++; + pv->set ( 1, 1, 1, 0, 0, scale_X, 0 ); pv++; + pv->set ( 1, -1, 1, 1, 0, scale_X, scale_Y ); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + + // Draw + RCache.set_Element (s_ssao->E[0] ); + RCache.set_Geometry (g_combine ); + + RCache.set_c ("m_v2w", m_v2w ); + RCache.set_c ("ssao_noise_tile_factor", fSSAONoise ); + RCache.set_c ("ssao_kernel_size", fSSAOKernelSize ); + RCache.set_c ("resolution", _w, _h, 1.0f / _w, 1.0f / _h ); + + + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + + glViewport(0, 0, float(Device.dwWidth), float(Device.dwHeight)); + + RCache.set_Stencil (FALSE); +} + + +void CRenderTarget::phase_downsamp () +{ + // DON'T DO THIS!!! + //IDirect3DSurface9 *source, *dest; + //rt_Position->pSurface->GetSurfaceLevel(0, &source); + //rt_half_depth->pSurface->GetSurfaceLevel(0, &dest); + //HW.pDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_POINT); + + //Fvector2 p0,p1; + u32 Offset = 0; + + // Targets + u_setrt ( rt_half_depth,0,0,0/*HW.pBaseZB*/ ); + + u32 clr4clear = color_rgba(0, 0, 0, 0); // 0x00 + CHK_DX(HW.pDevice->Clear(0L, NULL, D3DCLEAR_TARGET, clr4clear, 1.0f, 0L)); + + u32 w = Device.dwWidth; + u32 h = Device.dwHeight; + + if (RImplementation.o.ssao_half_data) + { + glViewport(0, 0, float(Device.dwWidth) * 0.5f, float(Device.dwHeight) * 0.5f); + w /= 2; + h /= 2; + } + + RCache.set_Stencil (FALSE); + + { + Fmatrix m_v2w; m_v2w.invert (Device.mView ); + + // Fill VB + float scale_X = float(w) / float(TEX_jitter); + float scale_Y = float(h) / float(TEX_jitter); + + // Fill vertex buffer + FVF::TL* pv = (FVF::TL*) RCache.Vertex.Lock (4,g_combine->vb_stride,Offset); + pv->set ( -1, 1, 0, 0, 0, 0, 0 ); pv++; + pv->set ( -1, -1, 0, 1, 0, 0, scale_Y ); pv++; + pv->set ( 1, 1, 1, 0, 0, scale_X, 0 ); pv++; + pv->set ( 1, -1, 1, 1, 0, scale_X, scale_Y ); pv++; + RCache.Vertex.Unlock (4,g_combine->vb_stride); + + // Draw + RCache.set_Element (s_ssao->E[1] ); + RCache.set_Geometry (g_combine ); + RCache.set_c ("m_v2w", m_v2w ); + + RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); + } + + if (RImplementation.o.ssao_half_data) + glViewport(0, 0, float(Device.dwWidth), float(Device.dwHeight)); +} \ No newline at end of file diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget_wallmarks.h b/src/Layers/xrRenderPC_GL/gl_rendertarget_wallmarks.h new file mode 100644 index 00000000000..8ad035b26dd --- /dev/null +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget_wallmarks.h @@ -0,0 +1 @@ +void phase_wallmarks (); diff --git a/src/Layers/xrRenderPC_GL/glr_constants.cpp b/src/Layers/xrRenderPC_GL/glr_constants.cpp new file mode 100644 index 00000000000..b2a48dbc803 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/glr_constants.cpp @@ -0,0 +1,166 @@ +#include "stdafx.h" +#pragma hdrstop + +#include "../xrRender/r_constants.h" + +void cl_sampler::setup(R_constant* C) +{ + CHK_GL(glProgramUniform1i(C->samp.program, C->samp.location, C->samp.index)); +} + +IC bool p_sort(ref_constant C1, ref_constant C2) +{ + return xr_strcmp(C1->name, C2->name)<0; +} + +// TODO: OGL: Use constant buffers like DX10. +BOOL R_constant_table::parse(void* _desc, u16 destination) +{ + GLuint program = *(GLuint*)_desc; + + // Get the maximum length of the constant name and allocate a buffer for it + GLint maxLength; + CHK_GL(glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength)); + GLchar* name = xr_alloc(maxLength + 1); // Null terminator + + // Iterate all uniforms and parse the entries for the constant table. + GLint uniformCount; + CHK_GL(glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniformCount)); + + u16 r_stage = 0; + for (GLint i = 0; i < uniformCount; i++) { + GLint size; + GLenum reg; + CHK_GL(glGetActiveUniform(program, i, maxLength, NULL, &size, ®, name)); + + // Remove index from arrays + if (size > 1) + { + char* str = strstr(name, "[0]"); + if (str) *str = '\0'; + } + + u16 type = RC_float; + if (GL_BOOL == reg || + GL_BOOL_VEC2 == reg || + GL_BOOL_VEC3 == reg || + GL_BOOL_VEC4 == reg) + type = RC_bool; + if (GL_INT == reg || + GL_INT_VEC2 == reg || + GL_INT_VEC3 == reg || + GL_INT_VEC4 == reg) + type = RC_int; + + // Rindex,Rcount,Rlocation + u16 r_index = i; + u16 r_type = u16(-1); + GLuint r_location = glGetUniformLocation(program, name); + + // TypeInfo + class + BOOL bSkip = FALSE; + switch (reg) + { + case GL_FLOAT: + case GL_BOOL: + case GL_INT: + r_type = RC_1x1; + break; + case GL_FLOAT_VEC2: + case GL_BOOL_VEC2: + case GL_INT_VEC2: + r_type = RC_1x2; + break; + case GL_FLOAT_VEC3: + case GL_BOOL_VEC3: + case GL_INT_VEC3: + r_type = RC_1x3; + break; + case GL_FLOAT_VEC4: + case GL_BOOL_VEC4: + case GL_INT_VEC4: + r_type = RC_1x4; + break; + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + fatal("GL_FLOAT_MAT: unsupported number of dimensions"); + break; + case GL_FLOAT_MAT4x2: + r_type = RC_2x4; + break; + case GL_FLOAT_MAT4x3: + r_type = RC_3x4; + break; + case GL_FLOAT_MAT4: + r_type = RC_4x4; + break; + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_SHADOW: + { + // ***Register sampler*** + // We have determined all valuable info, search if constant already created + // Assign an unused stage as the index + ref_constant C = get(name); + if (!C) { + C = new R_constant();//.g_constant_allocator.create(); + C->name = name; + C->destination = RC_dest_sampler; + C->type = RC_sampler; + C->handler = &sampler_binder; + R_constant_load& L = C->samp; + L.index = r_stage++; + L.cls = RC_sampler; + L.location = r_location; + L.program = program; + table.push_back(C); + } + else { + R_ASSERT(C->destination == RC_dest_sampler); + R_ASSERT(C->type == RC_sampler); + R_ASSERT(C->handler == &sampler_binder); + R_constant_load& L = C->samp; + R_ASSERT(L.index == r_stage); + R_ASSERT(L.cls == RC_sampler); + R_ASSERT(L.location == r_location); + R_ASSERT(L.program == program); + } + } + bSkip = TRUE; + break; + default: + fatal("unsupported uniform"); + bSkip = TRUE; + break; + } + if (bSkip) continue; + + // We have determined all valuable info, search if constant already created + ref_constant C = get (name); + if (!C) { + C = new R_constant();//.g_constant_allocator.create(); + C->name = name; + C->destination = destination; + C->type = type; + R_constant_load& L = (destination&1)?C->ps:C->vs; + L.index = r_index; + L.cls = r_type; + L.location = r_location; + L.program = program; + table.push_back (C); + } else { + C->destination |= destination; + VERIFY (C->type == type); + R_constant_load& L = (destination&1)?C->ps:C->vs; + L.index = r_index; + L.cls = r_type; + L.location = r_location; + L.program = program; + } + } + std::sort(table.begin(), table.end(), p_sort); + xr_free(name); + return TRUE; +} diff --git a/src/Layers/xrRenderPC_GL/r2_R_calculate.cpp b/src/Layers/xrRenderPC_GL/r2_R_calculate.cpp new file mode 100644 index 00000000000..3f6c8d02ce2 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/r2_R_calculate.cpp @@ -0,0 +1,71 @@ +#include "stdafx.h" +#include "../../xrEngine/customhud.h" + +float g_fSCREEN; + +extern float r_dtex_range; +extern float r_ssaDISCARD; +extern float r_ssaDONTSORT; +extern float r_ssaLOD_A; +extern float r_ssaLOD_B; +extern float r_ssaHZBvsTEX; +extern float r_ssaGLOD_start, r_ssaGLOD_end; + +void CRender::Calculate() +{ + // Transfer to global space to avoid deep pointer access + IRender_Target* T = getTarget(); + float fov_factor = _sqr(90.f / Device.fFOV); + g_fSCREEN = float(T->get_width()*T->get_height())*fov_factor*(EPS_S + ps_r__LOD); + r_ssaDISCARD = _sqr(ps_r__ssaDISCARD) / g_fSCREEN; + r_ssaDONTSORT = _sqr(ps_r__ssaDONTSORT / 3) / g_fSCREEN; + r_ssaLOD_A = _sqr(ps_r2_ssaLOD_A / 3) / g_fSCREEN; + r_ssaLOD_B = _sqr(ps_r2_ssaLOD_B / 3) / g_fSCREEN; + r_ssaGLOD_start = _sqr(ps_r__GLOD_ssa_start / 3) / g_fSCREEN; + r_ssaGLOD_end = _sqr(ps_r__GLOD_ssa_end / 3) / g_fSCREEN; + r_ssaHZBvsTEX = _sqr(ps_r__ssaHZBvsTEX / 3) / g_fSCREEN; + r_dtex_range = ps_r2_df_parallax_range * g_fSCREEN / (1024.f * 768.f); + + // Detect camera-sector + if (!vLastCameraPos.similar(Device.vCameraPosition, EPS_S)) + { + CSector* pSector = (CSector*)detectSector(Device.vCameraPosition); + if (pSector && (pSector != pLastSector)) + g_pGamePersistent->OnSectorChanged(translateSector(pSector)); + + if (0 == pSector) pSector = pLastSector; + pLastSector = pSector; + vLastCameraPos.set(Device.vCameraPosition); + } + + // Check if camera is too near to some portal - if so force DualRender + if (rmPortals) + { + float eps = VIEWPORT_NEAR + EPS_L; + Fvector box_radius; box_radius.set(eps, eps, eps); + Sectors_xrc.box_options(CDB::OPT_FULL_TEST); + Sectors_xrc.box_query(rmPortals, Device.vCameraPosition, box_radius); + for (int K = 0; Kget_tris()[Sectors_xrc.r_begin()[K].id].dummy]; + pPortal->bDualRender = TRUE; + } + } + + // + Lights.Update(); + + // Check if we touch some light even trough portal + lstRenderables.clear(); + g_SpatialSpace->q_sphere(lstRenderables, 0, STYPE_LIGHTSOURCE, Device.vCameraPosition, EPS_L); + for (u32 _it = 0; _itspatial_updatesector(); + CSector* sector = (CSector*)spatial->spatial.sector; + if (0 == sector) continue; // disassociated from S/P structure + + VERIFY(spatial->spatial.type & STYPE_LIGHTSOURCE); + // lightsource + light* L = (light*)(spatial->dcast_Light()); + VERIFY(L); + Lights.add_light(L); + } +} diff --git a/src/Layers/xrRenderPC_GL/r2_R_lights.cpp b/src/Layers/xrRenderPC_GL/r2_R_lights.cpp new file mode 100644 index 00000000000..6728c8d7651 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/r2_R_lights.cpp @@ -0,0 +1,235 @@ +#include "stdafx.h" + +IC bool pred_area (light* _1, light* _2) +{ + u32 a0 = _1->X.S.size; + u32 a1 = _2->X.S.size; + return a0>a1; // reverse -> descending +} + +void CRender::render_lights (light_Package& LP) +{ + ////////////////////////////////////////////////////////////////////////// + // Refactor order based on ability to pack shadow-maps + // 1. calculate area + sort in descending order + // const u16 smap_unassigned = u16(-1); + { + xr_vector& source = LP.v_shadowed; + for (u32 it=0; itvis_update (); + if (!L->vis.visible) { + source.erase (source.begin()+it); + it--; + } else { + LR.compute_xf_spot (L); + } + } + } + + // 2. refactor - infact we could go from the backside and sort in ascending order + { + xr_vector& source = LP.v_shadowed; + xr_vector refactored ; + refactored.reserve (source.size()); + u32 total = source.size(); + + for (u16 smap_ID=0; refactored.size()!=total; smap_ID++) + { + LP_smap_pool.initialize (RImplementation.o.smapsize); + std::sort (source.begin(),source.end(),pred_area); + for (u32 test=0; testX.S.size)) { + // OK + L->X.S.posX = R.min.x; + L->X.S.posY = R.min.y; + L->vis.smap_ID = smap_ID; + refactored.push_back(L); + source.erase (source.begin()+test); + test --; + } + } + } + + // save (lights are popped from back) + std::reverse (refactored.begin(),refactored.end()); + LP.v_shadowed = refactored; + } + + ////////////////////////////////////////////////////////////////////////// + // sort lights by importance??? + // while (has_any_lights_that_cast_shadows) { + // if (has_point_shadowed) -> generate point shadowmap + // if (has_spot_shadowed) -> generate spot shadowmap + // switch-to-accumulator + // if (has_point_unshadowed) -> accum point unshadowed + // if (has_spot_unshadowed) -> accum spot unshadowed + // if (was_point_shadowed) -> accum point shadowed + // if (was_spot_shadowed) -> accum spot shadowed + // } + // if (left_some_lights_that_doesn't cast shadows) + // accumulate them + HOM.Disable (); + while (LP.v_shadowed.size() ) + { + // if (has_spot_shadowed) + xr_vector L_spot_s; + stats.s_used ++; + + // generate spot shadowmap + Target->phase_smap_spot_clear (); + xr_vector& source = LP.v_shadowed; + light* L = source.back () ; + u16 sid = L->vis.smap_ID ; + while (true) + { + if (source.empty()) break; + L = source.back (); + if (L->vis.smap_ID!=sid) break; + source.pop_back (); + Lights_LastFrame.push_back (L); + + // render + phase = PHASE_SMAP; + if (RImplementation.o.Tshadows) r_pmask (true,true ); + else r_pmask (true,false ); + L->svis.begin (); + r_dsgraph_render_subspace (L->spatial.sector, L->X.S.combine, L->position, TRUE); + bool bNormal = mapNormalPasses[0][0].size() || mapMatrixPasses[0][0].size(); + bool bSpecial = mapNormalPasses[1][0].size() || mapMatrixPasses[1][0].size() || mapSorted.size(); + if ( bNormal || bSpecial) { + stats.s_merged ++; + L_spot_s.push_back (L); + Target->phase_smap_spot (L); + RCache.set_xform_world (Fidentity); + RCache.set_xform_view (L->X.S.view); + RCache.set_xform_project (L->X.S.project); + r_dsgraph_render_graph (0); + L->X.S.transluent = FALSE; + if (bSpecial) { + L->X.S.transluent = TRUE; + Target->phase_smap_spot_tsh (L); + r_dsgraph_render_graph (1); // normal level, secondary priority + r_dsgraph_render_sorted ( ); // strict-sorted geoms + } + } else { + stats.s_finalclip ++; + } + L->svis.end (); + r_pmask (true,false); + } + + // switch-to-accumulator + Target->phase_accumulator (); + HOM.Disable (); + + // if (has_point_unshadowed) -> accum point unshadowed + if (!LP.v_point.empty()) { + light* L = LP.v_point.back (); LP.v_point.pop_back (); + L->vis_update (); + if (L->vis.visible) { + Target->accum_point (L); + render_indirect (L); + } + } + + // if (has_spot_unshadowed) -> accum spot unshadowed + if (!LP.v_spot.empty()) { + light* L = LP.v_spot.back (); LP.v_spot.pop_back (); + L->vis_update (); + if (L->vis.visible) { + LR.compute_xf_spot (L); + Target->accum_spot (L); + render_indirect (L); + } + } + + // if (was_spot_shadowed) -> accum spot shadowed + if (!L_spot_s.empty()) + { + for (u32 it=0; itaccum_spot (L_spot_s[it]); + render_indirect (L_spot_s[it]); + } + + if (RImplementation.o.advancedpp && ps_r2_ls_flags.is(R2FLAG_VOLUMETRIC_LIGHTS)) + for (u32 it=0; itaccum_volumetric(L_spot_s[it]); + + L_spot_s.clear (); + } + } + + // Point lighting (unshadowed, if left) + if (!LP.v_point.empty()) { + xr_vector& Lvec = LP.v_point; + for (u32 pid=0; pidvis_update (); + if (Lvec[pid]->vis.visible) { + render_indirect (Lvec[pid]); + Target->accum_point (Lvec[pid]); + } + } + Lvec.clear (); + } + + // Spot lighting (unshadowed, if left) + if (!LP.v_spot.empty()) { + xr_vector& Lvec = LP.v_spot; + for (u32 pid=0; pidvis_update (); + if (Lvec[pid]->vis.visible) { + LR.compute_xf_spot (Lvec[pid]); + render_indirect (Lvec[pid]); + Target->accum_spot (Lvec[pid]); + } + } + Lvec.clear (); + } +} + +void CRender::render_indirect (light* L) +{ + if (!ps_r2_ls_flags.test(R2FLAG_GI)) return; + + light LIGEN; + LIGEN.set_type (IRender_Light::REFLECTED); + LIGEN.set_shadow (false); + LIGEN.set_cone (PI_DIV_2*2.f); + + xr_vector& Lvec = L->indirect; + if (Lvec.empty()) return; + float LE = L->color.intensity (); + for (u32 it=0; itcolor.r,L->color.g,L->color.b).mul(LI.E); + LIGEN.set_color (T.x,T.y,T.z); + + // geometric + Fvector L_up,L_right; L_up.set (0,1,0); if (_abs(L_up.dotproduct(LI.D))>.99f) L_up.set(0,0,1); + L_right.crossproduct (L_up,LI.D).normalize (); + LIGEN.spatial.sector = LI.S; + LIGEN.set_position (LI.P); + LIGEN.set_rotation (LI.D,L_right); + + // range + // dist^2 / range^2 = A - has infinity number of solutions + // approximate energy by linear fallof Emax / (1 + x) = Emin + float Emax = LIE; + float Emin = 1.f / 255.f; + float x = (Emax - Emin)/Emin; + if (x < 0.1f) continue; + LIGEN.set_range (x); + + Target->accum_reflected (&LIGEN); + } +} diff --git a/src/Layers/xrRenderPC_GL/r2_R_sun.cpp b/src/Layers/xrRenderPC_GL/r2_R_sun.cpp new file mode 100644 index 00000000000..1e9248cc501 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/r2_R_sun.cpp @@ -0,0 +1,1125 @@ +#include "stdafx.h" +#include "../../xrEngine/igame_persistent.h" +#include "../../xrEngine/irenderable.h" +#include "../xrRender/FBasicVisual.h" + +#include + +#pragma comment( lib, "d3dx9.lib" ) + +const float tweak_COP_initial_offs = 1200.f ; +const float tweak_ortho_xform_initial_offs = 1000.f ; //. ? +const float tweak_guaranteed_range = 20.f ; //. ? + +//float OLES_SUN_LIMIT_27_01_07 = 180.f ; +float OLES_SUN_LIMIT_27_01_07 = 100.f ; + +////////////////////////////////////////////////////////////////////////// +// tables to calculate view-frustum bounds in world space +// note: D3D uses [0..1] range for Z +static Fvector3 corners [8] = { + { -1, -1, 0 }, { -1, -1, +1}, + { -1, +1, +1 }, { -1, +1, 0}, + { +1, +1, +1 }, { +1, +1, 0}, + { +1, -1, +1}, { +1, -1, 0} +}; +static int facetable[6][4] = { + { 0, 3, 5, 7 }, { 1, 2, 3, 0 }, + { 6, 7, 5, 4 }, { 4, 2, 1, 6 }, + { 3, 2, 4, 5 }, { 1, 0, 7, 6 }, +}; +////////////////////////////////////////////////////////////////////////// +#define DW_AS_FLT(DW) (*(FLOAT*)&(DW)) +#define FLT_AS_DW(F) (*(DWORD*)&(F)) +#define FLT_SIGN(F) ((FLT_AS_DW(F) & 0x80000000L)) +#define ALMOST_ZERO(F) ((FLT_AS_DW(F) & 0x7f800000L)==0) +#define IS_SPECIAL(F) ((FLT_AS_DW(F) & 0x7f800000L)==0x7f800000L) + +////////////////////////////////////////////////////////////////////////// +struct Frustum +{ + Frustum (); + Frustum ( const D3DXMATRIX* matrix ); + + D3DXPLANE camPlanes [6]; + int nVertexLUT [6]; + D3DXVECTOR3 pntList [8]; +}; +struct BoundingBox +{ + D3DXVECTOR3 minPt; + D3DXVECTOR3 maxPt; + + BoundingBox(): minPt(1e33f, 1e33f, 1e33f), maxPt(-1e33f, -1e33f, -1e33f) { } + BoundingBox( const BoundingBox& other ): minPt(other.minPt), maxPt(other.maxPt) { } + + explicit BoundingBox( const D3DXVECTOR3* points, UINT n ): minPt(1e33f, 1e33f, 1e33f), maxPt(-1e33f, -1e33f, -1e33f) + { + for ( unsigned int i=0; i* points): minPt(1e33f, 1e33f, 1e33f), maxPt(-1e33f, -1e33f, -1e33f) + { + for ( unsigned int i=0; isize(); i++ ) + Merge( &(*points)[i] ); + } + explicit BoundingBox( const std::vector* boxes ): minPt(1e33f, 1e33f, 1e33f), maxPt(-1e33f, -1e33f, -1e33f) + { + for (unsigned int i=0; isize(); i++) + { + Merge( &(*boxes)[i].maxPt ); + Merge( &(*boxes)[i].minPt ); + } + } + void Centroid( D3DXVECTOR3* vec) const { *vec = 0.5f*(minPt+maxPt); } + void Merge( const D3DXVECTOR3* vec ) + { + minPt.x = _min(minPt.x, vec->x); + minPt.y = _min(minPt.y, vec->y); + minPt.z = _min(minPt.z, vec->z); + maxPt.x = _max(maxPt.x, vec->x); + maxPt.y = _max(maxPt.y, vec->y); + maxPt.z = _max(maxPt.z, vec->z); + } + D3DXVECTOR3 Point(int i) const { return D3DXVECTOR3( (i&1)?minPt.x:maxPt.x, (i&2)?minPt.y:maxPt.y, (i&4)?minPt.z:maxPt.z ); } +}; + +/////////////////////////////////////////////////////////////////////////// +BOOL LineIntersection2D( D3DXVECTOR2* result, const D3DXVECTOR2* lineA, const D3DXVECTOR2* lineB ) +{ + // if the lines are parallel, the lines will not intersect in a point + // NOTE: assumes the rays are already normalized!!!! + VERIFY ( _abs(D3DXVec2Dot(&lineA[1], &lineB[1]))<1.f ); + + float x[2] = { lineA[0].x, lineB[0].x }; + float y[2] = { lineA[0].y, lineB[0].y }; + float dx[2] = { lineA[1].x, lineB[1].x }; + float dy[2] = { lineA[1].y, lineB[1].y }; + + float x_diff = x[0] - x[1]; + float y_diff = y[0] - y[1]; + + float s = (x_diff - (dx[1]/dy[1])*y_diff) / ((dx[1]*dy[0]/dy[1])-dx[0]); + // float t = (x_diff + s*dx[0]) / dx[1]; + + *result = lineA[0] + s*lineA[1]; + return TRUE; +} +/////////////////////////////////////////////////////////////////////////// +// PlaneIntersection +// computes the point where three planes intersect +// returns whether or not the point exists. +static inline BOOL PlaneIntersection( D3DXVECTOR3* intersectPt, const D3DXPLANE* p0, const D3DXPLANE* p1, const D3DXPLANE* p2 ) +{ + D3DXVECTOR3 n0( p0->a, p0->b, p0->c ); + D3DXVECTOR3 n1( p1->a, p1->b, p1->c ); + D3DXVECTOR3 n2( p2->a, p2->b, p2->c ); + + D3DXVECTOR3 n1_n2, n2_n0, n0_n1; + + D3DXVec3Cross( &n1_n2, &n1, &n2 ); + D3DXVec3Cross( &n2_n0, &n2, &n0 ); + D3DXVec3Cross( &n0_n1, &n0, &n1 ); + + float cosTheta = D3DXVec3Dot( &n0, &n1_n2 ); + + if ( ALMOST_ZERO(cosTheta) || IS_SPECIAL(cosTheta) ) + return FALSE; + + float secTheta = 1.f / cosTheta; + + n1_n2 = n1_n2 * p0->d; + n2_n0 = n2_n0 * p1->d; + n0_n1 = n0_n1 * p2->d; + + *intersectPt = -(n1_n2 + n2_n0 + n0_n1) * secTheta; + return TRUE; +} + +Frustum::Frustum() +{ + for (int i=0; i<6; i++) + camPlanes[i] = D3DXPLANE(0.f, 0.f, 0.f, 0.f); +} + +// build a frustum from a camera (projection, or viewProjection) matrix +Frustum::Frustum(const D3DXMATRIX* matrix) +{ + // build a view frustum based on the current view & projection matrices... + D3DXVECTOR4 column4( matrix->_14, matrix->_24, matrix->_34, matrix->_44 ); + D3DXVECTOR4 column1( matrix->_11, matrix->_21, matrix->_31, matrix->_41 ); + D3DXVECTOR4 column2( matrix->_12, matrix->_22, matrix->_32, matrix->_42 ); + D3DXVECTOR4 column3( matrix->_13, matrix->_23, matrix->_33, matrix->_43 ); + + D3DXVECTOR4 planes[6]; + planes[0] = column4 - column1; // left + planes[1] = column4 + column1; // right + planes[2] = column4 - column2; // bottom + planes[3] = column4 + column2; // top + planes[4] = column4 - column3; // near + planes[5] = column4 + column3; // far + // ignore near & far plane + + int p; + + for (p=0; p<6; p++) // normalize the planes + { + float dot = planes[p].x*planes[p].x + planes[p].y*planes[p].y + planes[p].z*planes[p].z; + dot = 1.f / _sqrt(dot); + planes[p] = planes[p] * dot; + } + + for (p=0; p<6; p++) + camPlanes[p] = D3DXPLANE( planes[p].x, planes[p].y, planes[p].z, planes[p].w ); + + // build a bit-field that will tell us the indices for the nearest and farthest vertices from each plane... + for (int i=0; i<6; i++) + nVertexLUT[i] = ((planes[i].x<0.f)?1:0) | ((planes[i].y<0.f)?2:0) | ((planes[i].z<0.f)?4:0); + + for (int i=0; i<8; i++) // compute extrema + { + const D3DXPLANE& p0 = (i&1)?camPlanes[4] : camPlanes[5]; + const D3DXPLANE& p1 = (i&2)?camPlanes[3] : camPlanes[2]; + const D3DXPLANE& p2 = (i&4)?camPlanes[0] : camPlanes[1]; + PlaneIntersection( &pntList[i], &p0, &p1, &p2 ); + } +} + +////////////////////////////////////////////////////////////////////////// +// OLES: naive builder of infinite volume expanded from base frustum towards +// light source. really slow, but it works for our simple usage :) +// note: normals points to 'outside' +////////////////////////////////////////////////////////////////////////// +template +class DumbConvexVolume +{ +public: + struct _poly + { + xr_vector points; + Fvector3 planeN; + float planeD; + float classify (Fvector3& p) { return planeN.dotproduct(p)+planeD; } + }; + struct _edge + { + int p0,p1; + int counter; + _edge (int _p0, int _p1, int m) : p0(_p0), p1(_p1), counter(m){ if (p0>p1) swap(p0,p1); } + bool equal (_edge& E) { return p0==E.p0 && p1==E.p1; } + }; +public: + xr_vector points; + xr_vector<_poly> polys; + xr_vector<_edge> edges; +public: + void compute_planes () + { + for (int it=0; it& dest, Fvector3 direction) + { + CRenderTarget& T = *RImplementation.Target; + + // COG + Fvector3 cog = {0,0,0}; + for (int it=0; it0) std::reverse(base.points.begin(),base.points.end()); + } + + // remove faceforward polys, build list of edges -> find open ones + compute_planes (); + for (int it=0; it& plist = polys[it].points; + for (int p=0; p0) std::reverse(base.points.begin(),base.points.end()); + } + + // Export + compute_planes (); + for (int it=0; it0.f); + float invW = 1.0f/r.w; + Fvector3 r3 = { r.x*invW, r.y*invW, r.z*invW }; + return r3; +} + +////////////////////////////////////////////////////////////////////////// +// OLES: naive 3D clipper - roubustness around 0, but works for this sample +// note: normals points to 'outside' +////////////////////////////////////////////////////////////////////////// +const float _eps = 0.000001f; +struct DumbClipper +{ + CFrustum frustum; + xr_vector planes; + BOOL clip (D3DXVECTOR3& p0, D3DXVECTOR3& p1) // returns TRUE if result meaningfull + { + float denum; + D3DXVECTOR3 D; + for (int it=0; it0 && cls1>0) return false; // fully outside + + if (cls0>0) { + // clip p0 + D = p1-p0; + denum = D3DXPlaneDotNormal(&P,&D); + if (denum!=0) p0 += - D * cls0 / denum; + } + if (cls1>0) { + // clip p1 + D = p0-p1; + denum = D3DXPlaneDotNormal(&P,&D); + if (denum!=0) p1 += - D * cls1 / denum; + } + } + return true; + } + D3DXVECTOR3 point (Fbox& bb, int i) const { return D3DXVECTOR3( (i&1)?bb.min.x:bb.max.x, (i&2)?bb.min.y:bb.max.y, (i&4)?bb.min.z:bb.max.z ); } + Fbox clipped_AABB(xr_vector >& src, Fmatrix& xf) + { + Fbox3 result; result.invalidate (); + for (int it=0; it +inline const _Tp& min(const _Tp& __a, const _Tp& __b) { + return __b < __a ? __b : __a; +} +template +inline const _Tp& max(const _Tp& __a, const _Tp& __b) { + return __a < __b ? __b : __a; +} + +xr_vector > s_casters; + +D3DXVECTOR2 BuildTSMProjectionMatrix_caster_depth_bounds(D3DXMATRIX& lightSpaceBasis) +{ + float min_z = 1e32f, max_z=-1e32f; + D3DXMATRIX minmax_xf; + D3DXMatrixMultiply (&minmax_xf,(D3DXMATRIX*)&Device.mView,&lightSpaceBasis); + Fmatrix& minmax_xform = *((Fmatrix*)&minmax_xf); + for (u32 c=0; cEnvironment().CurrentEnv->far_plane); + //ex_project.build_projection (deg2rad(Device.fFOV/* *Device.fASPECT*/),Device.fASPECT,ps_r2_sun_near,_far_); + ex_project.build_projection (deg2rad(Device.fFOV/* *Device.fASPECT*/),Device.fASPECT,VIEWPORT_NEAR,_far_); + ex_full.mul (ex_project,Device.mView); + D3DXMatrixInverse ((D3DXMATRIX*)&ex_full_inverse,0,(D3DXMATRIX*)&ex_full); + } + + // Compute volume(s) - something like a frustum for infinite directional light + // Also compute virtual light position and sector it is inside + CFrustum cull_frustum ; + xr_vector cull_planes ; + Fvector3 cull_COP ; + CSector* cull_sector ; + Fmatrix cull_xform ; + { + FPU::m64r (); + // Lets begin from base frustum + Fmatrix fullxform_inv = ex_full_inverse; + DumbConvexVolume hull; + { + hull.points.reserve (8); + for (int p=0; p<8; p++) { + Fvector3 xf = wform (fullxform_inv,corners[p]); + hull.points.push_back (xf); + } + for (int plane=0; plane<6; plane++) { + hull.polys.push_back(DumbConvexVolume::_poly()); + for (int pt=0; pt<4; pt++) + hull.polys.back().points.push_back(facetable[plane][pt]); + } + } + hull.compute_caster_model (cull_planes,fuckingsun->direction); + + // Search for default sector - assume "default" or "outdoor" sector is the largest one + //. hack: need to know real outdoor sector + CSector* largest_sector = 0; + float largest_sector_vol = 0; + for (u32 s=0; sroot() ; + float vol = V->vis.box.getvolume(); + if (vol>largest_sector_vol) { + largest_sector_vol = vol; + largest_sector = S; + } + } + cull_sector = largest_sector; + + // COP - 100 km away + cull_COP.mad (Device.vCameraPosition, fuckingsun->direction, -tweak_COP_initial_offs ); + + // Create frustum for query + cull_frustum._clear (); + for (u32 p=0; pposition); + L_dir.set (fuckingsun->direction).normalize (); + L_up.set (0,1,0); if (_abs(L_up.dotproduct(L_dir))>.99f) L_up.set(0,0,1); + L_right.crossproduct (L_up,L_dir).normalize (); + L_up.crossproduct (L_dir,L_right).normalize (); + mdir_View.build_camera_dir (L_pos,L_dir,L_up); + + // projection: box + Fbox frustum_bb; frustum_bb.invalidate(); + for (int it=0; it<8; it++) { + Fvector xf = wform (mdir_View,hull.points[it]); + frustum_bb.modify (xf); + } + Fbox& bb = frustum_bb; + bb.grow (EPS); + D3DXMatrixOrthoOffCenterLH ((D3DXMATRIX*)&mdir_Project,bb.min.x,bb.max.x, bb.min.y,bb.max.y, bb.min.z-tweak_ortho_xform_initial_offs,bb.max.z); + + // full-xform + cull_xform.mul (mdir_Project,mdir_View); + FPU::m24r (); + } + + // Begin SMAP-render + { + HOM.Disable (); + phase = PHASE_SMAP; + if (RImplementation.o.Tshadows) r_pmask (true,true ); + else r_pmask (true,false ); +// fuckingsun->svis.begin (); + } + + // Fill the database + xr_vector > &s_receivers = main_coarse_structure; + s_casters.reserve (s_receivers.size()); + set_Recorder (&s_casters); + r_dsgraph_render_subspace (cull_sector, &cull_frustum, cull_xform, cull_COP, TRUE); + + // IGNORE PORTALS + if (ps_r2_ls_flags.test(R2FLAG_SUN_IGNORE_PORTALS)) + { + for (u32 s=0; sroot() ; + + set_Frustum (&cull_frustum); + add_Geometry (root); + } + } + set_Recorder (NULL); + + // Prepare to interact with D3DX code + const D3DXMATRIX& m_View = *((D3DXMATRIX*)(&Device.mView)); + const D3DXMATRIX& m_Projection = *((D3DXMATRIX*)(&ex_project)); + const D3DXVECTOR3 m_lightDir = -D3DXVECTOR3(fuckingsun->direction.x,fuckingsun->direction.y,fuckingsun->direction.z); + + // these are the limits specified by the physical camera + // gamma is the "tilt angle" between the light and the view direction. + float m_fCosGamma = m_lightDir.x * m_View._13 + + m_lightDir.y * m_View._23 + + m_lightDir.z * m_View._33 ; + float m_fTSM_Delta= ps_r2_sun_tsm_projection; + + // Compute REAL sheared xform based on receivers/casters information + FPU::m64r (); + if ( _abs(m_fCosGamma) < 0.99f && ps_r2_ls_flags.test(R2FLAG_SUN_TSM)) + { + // get the near and the far plane (points) in eye space. + D3DXVECTOR3 frustumPnts[8]; + + Frustum eyeFrustum ( &m_Projection ); // autocomputes all the extrema points + + for ( int i=0; i<4; i++ ) + { + frustumPnts[i] = eyeFrustum.pntList[(i<<1)]; // far plane + frustumPnts[i+4] = eyeFrustum.pntList[(i<<1) | 0x1]; // near plane + } + + // we need to transform the eye into the light's post-projective space. + // however, the sun is a directional light, so we first need to find an appropriate + // rotate/translate matrix, before constructing an ortho projection. + // this matrix is a variant of "light space" from LSPSMs, with the Y and Z axes permuted + + D3DXVECTOR3 leftVector, upVector, viewVector; + const D3DXVECTOR3 eyeVector( 0.f, 0.f, -1.f ); // eye is always -Z in eye space + + // code copied straight from BuildLSPSMProjectionMatrix + D3DXVec3TransformNormal( &upVector, &m_lightDir, &m_View ); // lightDir is defined in eye space, so xform it + D3DXVec3Cross( &leftVector, &upVector, &eyeVector ); + D3DXVec3Normalize( &leftVector, &leftVector ); + D3DXVec3Cross( &viewVector, &upVector, &leftVector ); + + D3DXMATRIX lightSpaceBasis; + lightSpaceBasis._11 = leftVector.x; lightSpaceBasis._12 = viewVector.x; lightSpaceBasis._13 = -upVector.x; lightSpaceBasis._14 = 0.f; + lightSpaceBasis._21 = leftVector.y; lightSpaceBasis._22 = viewVector.y; lightSpaceBasis._23 = -upVector.y; lightSpaceBasis._24 = 0.f; + lightSpaceBasis._31 = leftVector.z; lightSpaceBasis._32 = viewVector.z; lightSpaceBasis._33 = -upVector.z; lightSpaceBasis._34 = 0.f; + lightSpaceBasis._41 = 0.f; lightSpaceBasis._42 = 0.f; lightSpaceBasis._43 = 0.f; lightSpaceBasis._44 = 1.f; + + // rotate the view frustum into light space + D3DXVec3TransformCoordArray( frustumPnts, sizeof(D3DXVECTOR3), frustumPnts, sizeof(D3DXVECTOR3), &lightSpaceBasis, sizeof(frustumPnts)/sizeof(D3DXVECTOR3) ); + + // build an off-center ortho projection that translates and scales the eye frustum's 3D AABB to the unit cube + BoundingBox frustumBox ( frustumPnts, sizeof(frustumPnts) / sizeof(D3DXVECTOR3) ); + + // also - transform the shadow caster bounding boxes into light projective space. we want to translate along the Z axis so that + // all shadow casters are in front of the near plane. + D3DXVECTOR2 depthbounds = BuildTSMProjectionMatrix_caster_depth_bounds (lightSpaceBasis); + + float min_z = min( depthbounds.x, frustumBox.minPt.z ); + float max_z = max( depthbounds.y, frustumBox.maxPt.z ); + + if ( min_z <= 1.f ) //? + { + D3DXMATRIX lightSpaceTranslate; + D3DXMatrixTranslation( &lightSpaceTranslate, 0.f, 0.f, -min_z + 1.f ); + max_z = -min_z + max_z + 1.f; + min_z = 1.f; + D3DXMatrixMultiply ( &lightSpaceBasis, &lightSpaceBasis, &lightSpaceTranslate ); + D3DXVec3TransformCoordArray( frustumPnts, sizeof(D3DXVECTOR3), frustumPnts, sizeof(D3DXVECTOR3), &lightSpaceTranslate, sizeof(frustumPnts)/sizeof(D3DXVECTOR3) ); + frustumBox = BoundingBox( frustumPnts, sizeof(frustumPnts)/sizeof(D3DXVECTOR3) ); + } + + D3DXMATRIX lightSpaceOrtho; + D3DXMatrixOrthoOffCenterLH( &lightSpaceOrtho, frustumBox.minPt.x, frustumBox.maxPt.x, frustumBox.minPt.y, frustumBox.maxPt.y, min_z, max_z ); + + // transform the view frustum by the new matrix + D3DXVec3TransformCoordArray( frustumPnts, sizeof(D3DXVECTOR3), frustumPnts, sizeof(D3DXVECTOR3), &lightSpaceOrtho, sizeof(frustumPnts)/sizeof(D3DXVECTOR3) ); + + D3DXVECTOR2 centerPts [2]; + // near plane + centerPts[0].x = 0.25f * (frustumPnts[4].x + frustumPnts[5].x + frustumPnts[6].x + frustumPnts[7].x); + centerPts[0].y = 0.25f * (frustumPnts[4].y + frustumPnts[5].y + frustumPnts[6].y + frustumPnts[7].y); + // far plane + centerPts[1].x = 0.25f * (frustumPnts[0].x + frustumPnts[1].x + frustumPnts[2].x + frustumPnts[3].x); + centerPts[1].y = 0.25f * (frustumPnts[0].y + frustumPnts[1].y + frustumPnts[2].y + frustumPnts[3].y); + + D3DXVECTOR2 centerOrig = (centerPts[0] + centerPts[1])*0.5f; + + D3DXMATRIX trapezoid_space; + + D3DXMATRIX xlate_center( 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + -centerOrig.x, -centerOrig.y, 0.f, 1.f ); + + D3DXVECTOR2 center_dirl = D3DXVECTOR2(centerPts[1] - centerOrig); + float half_center_len = D3DXVec2Length( ¢er_dirl); + float x_len = centerPts[1].x - centerOrig.x; + float y_len = centerPts[1].y - centerOrig.y; + + float cos_theta = x_len / half_center_len; + float sin_theta = y_len / half_center_len; + + D3DXMATRIX rot_center( cos_theta, -sin_theta, 0.f, 0.f, + sin_theta, cos_theta, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f ); + + // this matrix transforms the center line to y=0. + // since Top and Base are orthogonal to Center, we can skip computing the convex hull, and instead + // just find the view frustum X-axis extrema. The most negative is Top, the most positive is Base + // Point Q (trapezoid projection point) will be a point on the y=0 line. + D3DXMatrixMultiply( &trapezoid_space, &xlate_center, &rot_center ); + D3DXVec3TransformCoordArray( frustumPnts, sizeof(D3DXVECTOR3), frustumPnts, sizeof(D3DXVECTOR3), &trapezoid_space, sizeof(frustumPnts)/sizeof(D3DXVECTOR3) ); + + BoundingBox frustumAABB2D( frustumPnts, sizeof(frustumPnts)/sizeof(D3DXVECTOR3) ); + + float x_scale = max( _abs(frustumAABB2D.maxPt.x), _abs(frustumAABB2D.minPt.x) ); + float y_scale = max( _abs(frustumAABB2D.maxPt.y), _abs(frustumAABB2D.minPt.y) ); + x_scale = 1.f/x_scale; + y_scale = 1.f/y_scale; + + // maximize the area occupied by the bounding box + D3DXMATRIX scale_center( x_scale, 0.f, 0.f, 0.f, + 0.f, y_scale, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f ); + + D3DXMatrixMultiply( &trapezoid_space, &trapezoid_space, &scale_center ); + + // scale the frustum AABB up by these amounts (keep all values in the same space) + frustumAABB2D.minPt.x *= x_scale; + frustumAABB2D.maxPt.x *= x_scale; + frustumAABB2D.minPt.y *= y_scale; + frustumAABB2D.maxPt.y *= y_scale; + + // compute eta. + float lambda = frustumAABB2D.maxPt.x - frustumAABB2D.minPt.x; + float delta_proj = m_fTSM_Delta * lambda; //focusPt.x - frustumAABB2D.minPt.x; + const float xi = -0.6f; // - 0.6f; // 80% line + float eta = (lambda*delta_proj*(1.f+xi)) / (lambda*(1.f-xi)-2.f*delta_proj); + + // compute the projection point a distance eta from the top line. this point is on the center line, y=0 + D3DXVECTOR2 projectionPtQ( frustumAABB2D.maxPt.x + eta, 0.f ); + + // find the maximum slope from the projection point to any point in the frustum. this will be the + // projection field-of-view + float max_slope = -1e32f; + float min_slope = 1e32f; + + for ( int i=0; i < sizeof(frustumPnts)/sizeof(D3DXVECTOR3); i++ ) + { + D3DXVECTOR2 tmp( frustumPnts[i].x*x_scale, frustumPnts[i].y*y_scale ); + float x_dist = tmp.x - projectionPtQ.x; + if ( !(ALMOST_ZERO(tmp.y) || ALMOST_ZERO(x_dist))) + { + max_slope = max(max_slope, tmp.y/x_dist); + min_slope = min(min_slope, tmp.y/x_dist); + } + } + + float xn = eta; + float xf = lambda + eta; + + D3DXMATRIX ptQ_xlate(-1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + projectionPtQ.x, 0.f, 0.f, 1.f ); + D3DXMatrixMultiply( &trapezoid_space, &trapezoid_space, &ptQ_xlate ); + + // this shear balances the "trapezoid" around the y=0 axis (no change to the projection pt position) + // since we are redistributing the trapezoid, this affects the projection field of view (shear_amt) + float shear_amt = (max_slope + _abs(min_slope))*0.5f - max_slope; + max_slope = max_slope + shear_amt; + + D3DXMATRIX trapezoid_shear( 1.f, shear_amt, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f ); + + D3DXMatrixMultiply( &trapezoid_space, &trapezoid_space, &trapezoid_shear ); + + + float z_aspect = (frustumBox.maxPt.z-frustumBox.minPt.z) / (frustumAABB2D.maxPt.y-frustumAABB2D.minPt.y); + + // perform a 2DH projection to 'unsqueeze' the top line. + D3DXMATRIX trapezoid_projection( xf/(xf-xn), 0.f, 0.f, 1.f, + 0.f, 1.f/max_slope, 0.f, 0.f, + 0.f, 0.f, 1.f/(z_aspect*max_slope), 0.f, + -xn*xf/(xf-xn), 0.f, 0.f, 0.f ); + + D3DXMatrixMultiply( &trapezoid_space, &trapezoid_space, &trapezoid_projection ); + + // the x axis is compressed to [0..1] as a result of the projection, so expand it to [-1,1] + D3DXMATRIX biasedScaleX( 2.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + -1.f, 0.f, 0.f, 1.f ); + D3DXMatrixMultiply ( &trapezoid_space, &trapezoid_space, &biasedScaleX ); + + D3DXMatrixMultiply ( &m_LightViewProj, &m_View, &lightSpaceBasis ); + D3DXMatrixMultiply ( &m_LightViewProj, &m_LightViewProj, &lightSpaceOrtho ); + D3DXMatrixMultiply ( &m_LightViewProj, &m_LightViewProj, &trapezoid_space ); + } else { + m_LightViewProj = *((D3DXMATRIX*)(&cull_xform)); + } + FPU::m24r (); + + // perform "refit" or "focusing" on relevant + if (ps_r2_ls_flags.test(R2FLAG_SUN_FOCUS)) + { + FPU::m64r (); + + // create clipper + DumbClipper view_clipper; + Fmatrix& xform = *((Fmatrix*)&m_LightViewProj); + view_clipper.frustum.CreateFromMatrix(ex_full,FRUSTUM_P_ALL); + for (int p=0; p+1) b_receivers.max.x =+1; + if (b_receivers.max.y>+1) b_receivers.max.y =+1; + if (b_casters.max.z>+1) b_casters.max.z =+1; + + // refit? + /* + const float EPS = 0.001f; + D3DXMATRIX refit; + D3DXMatrixOrthoOffCenterLH ( &refit, b_receivers.min.x, b_receivers.max.x, b_receivers.min.y, b_receivers.max.y, b_casters.min.z-EPS, b_casters.max.z+EPS ); + D3DXMatrixMultiply ( &m_LightViewProj, &m_LightViewProj, &refit); + */ + + float boxWidth = b_receivers.max.x - b_receivers.min.x; + float boxHeight = b_receivers.max.y - b_receivers.min.y; + // the divide by two's cancel out in the translation, but included for clarity + float boxX = (b_receivers.max.x+b_receivers.min.x) / 2.f; + float boxY = (b_receivers.max.y+b_receivers.min.y) / 2.f; + D3DXMATRIX trapezoidUnitCube ( 2.f/boxWidth, 0.f, 0.f, 0.f, + 0.f, 2.f/boxHeight, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + -2.f*boxX/boxWidth, -2.f*boxY/boxHeight, 0.f, 1.f ); + D3DXMatrixMultiply ( &m_LightViewProj, &m_LightViewProj, &trapezoidUnitCube); + //D3DXMatrixMultiply( &trapezoid_space, &trapezoid_space, &trapezoidUnitCube ); + FPU::m24r (); + } + + // Finalize & Cleanup + fuckingsun->X.D.combine = *((Fmatrix*)&m_LightViewProj); + s_receivers.clear (); + s_casters.clear (); + + // Render shadow-map + //. !!! We should clip based on shrinked frustum (again) + { + bool bNormal = mapNormalPasses[0][0].size() || mapMatrixPasses[0][0].size(); + bool bSpecial = mapNormalPasses[1][0].size() || mapMatrixPasses[1][0].size() || mapSorted.size(); + if ( bNormal || bSpecial) { + Target->phase_smap_direct (fuckingsun, SE_SUN_FAR ); + RCache.set_xform_world (Fidentity ); + RCache.set_xform_view (Fidentity ); + RCache.set_xform_project (fuckingsun->X.D.combine ); + r_dsgraph_render_graph (0); + fuckingsun->X.D.transluent = FALSE; + if (bSpecial) { + fuckingsun->X.D.transluent = TRUE; + Target->phase_smap_direct_tsh (fuckingsun, SE_SUN_FAR ); + r_dsgraph_render_graph (1); // normal level, secondary priority + r_dsgraph_render_sorted ( ); // strict-sorted geoms + } + } + } + + // End SMAP-render + { +// fuckingsun->svis.end (); + r_pmask (true,false); + } + + // Accumulate + Target->phase_accumulator (); + Target->accum_direct (SE_SUN_FAR); + + // Restore XForms + RCache.set_xform_world (Fidentity ); + RCache.set_xform_view (Device.mView ); + RCache.set_xform_project (Device.mProject ); +} + +void CRender::render_sun_near () +{ + light* fuckingsun = (light*)Lights.sun_adapted._get() ; + D3DXMATRIX m_LightViewProj ; + + // calculate view-frustum bounds in world space + Fmatrix ex_project, ex_full, ex_full_inverse; + { + ex_project.build_projection (deg2rad(Device.fFOV/* *Device.fASPECT*/),Device.fASPECT,VIEWPORT_NEAR,ps_r2_sun_near); + ex_full.mul (ex_project,Device.mView); + D3DXMatrixInverse ((D3DXMATRIX*)&ex_full_inverse,0,(D3DXMATRIX*)&ex_full); + } + + // Compute volume(s) - something like a frustum for infinite directional light + // Also compute virtual light position and sector it is inside + CFrustum cull_frustum; + xr_vector cull_planes; + Fvector3 cull_COP; + CSector* cull_sector; + Fmatrix cull_xform; + { + FPU::m64r (); + // Lets begin from base frustum + Fmatrix fullxform_inv = ex_full_inverse; +#ifdef _DEBUG + typedef DumbConvexVolume t_volume; +#else + typedef DumbConvexVolume t_volume; +#endif + t_volume hull; + { + hull.points.reserve (9); + for (int p=0; p<8; p++) { + Fvector3 xf = wform (fullxform_inv,corners[p]); + hull.points.push_back (xf); + } + for (int plane=0; plane<6; plane++) { + hull.polys.push_back(t_volume::_poly()); + for (int pt=0; pt<4; pt++) + hull.polys.back().points.push_back(facetable[plane][pt]); + } + } + hull.compute_caster_model (cull_planes,fuckingsun->direction); +#ifdef _DEBUG + for (u32 it=0; itdbg_addplane(cull_planes[it],0xffffffff); +#endif + + // Search for default sector - assume "default" or "outdoor" sector is the largest one + //. hack: need to know real outdoor sector + CSector* largest_sector = 0; + float largest_sector_vol = 0; + for (u32 s=0; sroot() ; + float vol = V->vis.box.getvolume(); + if (vol>largest_sector_vol) { + largest_sector_vol = vol; + largest_sector = S; + } + } + cull_sector = largest_sector; + + // COP - 100 km away + cull_COP.mad (Device.vCameraPosition, fuckingsun->direction, -tweak_COP_initial_offs ); + + // Create frustum for query + cull_frustum._clear (); + for (u32 p=0; pposition); + L_dir.set (fuckingsun->direction).normalize (); + L_right.set (1,0,0); if (_abs(L_right.dotproduct(L_dir))>.99f) L_right.set(0,0,1); + L_up.crossproduct (L_dir,L_right).normalize (); + L_right.crossproduct (L_up,L_dir).normalize (); + mdir_View.build_camera_dir (L_pos,L_dir,L_up); + + // projection: box + /* + // Original + float _D = ps_r2_sun_near; + float a0 = deg2rad(Device.fFOV*Device.fASPECT)/2.f; + float a1 = deg2rad(Device.fFOV)/2.f; + float c0 = _D/_cos(a0); + float c1 = _D/_cos(a1); + float k0 = 2.f*c0*_sin(a0); + float k1 = 2.f*c1*_sin(a1); + float borderalpha = (Device.fFOV-10) / (90-10); + + float nearborder = 1*borderalpha + 1.136363636364f*(1-borderalpha); + float spherical_range = ps_r2_sun_near_border * nearborder * _max(_max(c0,c1), _max(k0,k1)*1.414213562373f ); + Fbox frustum_bb; frustum_bb.invalidate (); + hull.points.push_back (Device.vCameraPosition); + for (int it=0; it<9; it++) { + Fvector xf = wform (mdir_View,hull.points[it]); + frustum_bb.modify (xf); + } + float size_x = frustum_bb.max.x - frustum_bb.min.x; + float size_y = frustum_bb.max.y - frustum_bb.min.y; + float diff_x = (spherical_range - size_x)/2.f; //VERIFY(diff_x>=0); + float diff_y = (spherical_range - size_y)/2.f; //VERIFY(diff_y>=0); + frustum_bb.min.x -= diff_x; frustum_bb.max.x += diff_x; + frustum_bb.min.y -= diff_y; frustum_bb.max.y += diff_y; + Fbox& bb = frustum_bb; + D3DXMatrixOrthoOffCenterLH ((D3DXMATRIX*)&mdir_Project,bb.min.x,bb.max.x, bb.min.y,bb.max.y, bb.min.z-tweak_ortho_xform_initial_offs,bb.max.z); + /**/ + + // Simple + Fbox frustum_bb; frustum_bb.invalidate(); + for (int it=0; it<8; it++) { + //for (int it=0; it<9; it++) { + Fvector xf = wform (mdir_View,hull.points[it]); + frustum_bb.modify (xf); + } + Fbox& bb = frustum_bb; + bb.grow (EPS); + D3DXMatrixOrthoOffCenterLH ((D3DXMATRIX*)&mdir_Project,bb.min.x,bb.max.x, bb.min.y,bb.max.y, bb.min.z-tweak_ortho_xform_initial_offs,bb.max.z); + /**/ + + // build viewport xform + float view_dim = float(RImplementation.o.smapsize); + Fmatrix m_viewport = { + view_dim/2.f, 0.0f, 0.0f, 0.0f, + 0.0f, -view_dim/2.f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + view_dim/2.f, view_dim/2.f, 0.0f, 1.0f + }; + Fmatrix m_viewport_inv; + D3DXMatrixInverse ((D3DXMATRIX*)&m_viewport_inv,0,(D3DXMATRIX*)&m_viewport); + + // snap view-position to pixel + cull_xform.mul (mdir_Project,mdir_View ); + Fvector cam_proj = wform (cull_xform,Device.vCameraPosition ); + Fvector cam_pixel = wform (m_viewport,cam_proj ); + cam_pixel.x = floorf (cam_pixel.x); + cam_pixel.y = floorf (cam_pixel.y); + Fvector cam_snapped = wform (m_viewport_inv,cam_pixel); + Fvector diff; diff.sub (cam_snapped,cam_proj ); + Fmatrix adjust; adjust.translate(diff); + cull_xform.mulA_44 (adjust); + + // calculate scissor + Fbox scissor ; scissor.invalidate(); + Fmatrix scissor_xf ; + scissor_xf.mul (m_viewport,cull_xform); + for (int it=0; it<9; it++) { + Fvector xf = wform (scissor_xf,hull.points[it]); + scissor.modify (xf); + } + s32 limit = RImplementation.o.smapsize-1; + fuckingsun->X.D.minX = clampr (iFloor (scissor.min.x), 0, limit); + fuckingsun->X.D.maxX = clampr (iCeil (scissor.max.x), 0, limit); + fuckingsun->X.D.minY = clampr (iFloor (scissor.min.y), 0, limit); + fuckingsun->X.D.maxY = clampr (iCeil (scissor.max.y), 0, limit); + + // full-xform + FPU::m24r (); + } + + // Begin SMAP-render + { + bool bSpecialFull = mapNormalPasses[1][0].size() || mapMatrixPasses[1][0].size() || mapSorted.size(); + VERIFY (!bSpecialFull); + HOM.Disable (); + phase = PHASE_SMAP; + if (RImplementation.o.Tshadows) r_pmask (true,true ); + else r_pmask (true,false ); +// fuckingsun->svis.begin (); + } + + // Fill the database + r_dsgraph_render_subspace (cull_sector, &cull_frustum, cull_xform, cull_COP, TRUE); + + // Finalize & Cleanup + fuckingsun->X.D.combine = cull_xform; //*((Fmatrix*)&m_LightViewProj); + + // Render shadow-map + //. !!! We should clip based on shrinked frustum (again) + { + bool bNormal = mapNormalPasses[0][0].size() || mapMatrixPasses[0][0].size(); + bool bSpecial = mapNormalPasses[1][0].size() || mapMatrixPasses[1][0].size() || mapSorted.size(); + if ( bNormal || bSpecial) { + Target->phase_smap_direct (fuckingsun , SE_SUN_NEAR ); + RCache.set_xform_world (Fidentity ); + RCache.set_xform_view (Fidentity ); + RCache.set_xform_project (fuckingsun->X.D.combine ); + r_dsgraph_render_graph (0) ; + if (ps_r2_ls_flags.test(R2FLAG_SUN_DETAILS)) + Details->Render () ; + fuckingsun->X.D.transluent = FALSE; + if (bSpecial) { + fuckingsun->X.D.transluent = TRUE; + Target->phase_smap_direct_tsh (fuckingsun, SE_SUN_NEAR); + r_dsgraph_render_graph (1); // normal level, secondary priority + r_dsgraph_render_sorted ( ); // strict-sorted geoms + } + } + } + + // End SMAP-render + { +// fuckingsun->svis.end (); + r_pmask (true,false); + } + + // Accumulate + Target->phase_accumulator (); + Target->accum_direct (SE_SUN_NEAR); + + // Restore XForms + RCache.set_xform_world (Fidentity ); + RCache.set_xform_view (Device.mView ); + RCache.set_xform_project (Device.mProject ); +} + +void CRender::render_sun_filtered () +{ + if (!RImplementation.o.sunfilter) return; + Target->phase_accumulator (); + Target->accum_direct (SE_SUN_LUMINANCE); +} diff --git a/src/Layers/xrRenderPC_GL/r2_blenders.cpp b/src/Layers/xrRenderPC_GL/r2_blenders.cpp new file mode 100644 index 00000000000..72700d82ae7 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/r2_blenders.cpp @@ -0,0 +1,51 @@ +#include "stdafx.h" + +#include "../xrRender/uber_deffer.h" + +#include "../xrRender/blender_BmmD.h" +#include "blender_deffer_flat.h" +#include "blender_deffer_model.h" +#include "blender_deffer_aref.h" +#include "../xrRender/blender_screen_set.h" +#include "../xrRender/blender_editor_wire.h" +#include "../xrRender/blender_editor_selection.h" +#include "../xrRender/blender_tree.h" +#include "../xrRender/blender_detail_still.h" +#include "../xrRender/blender_particle.h" +#include "../xrRender/Blender_Model_EbB.h" +#include "../xrRender/blender_Lm(EbB).h" + +IBlender* CRender::blender_create (CLASS_ID cls) +{ + switch (cls) + { + case B_DEFAULT: return new CBlender_deffer_flat(); + case B_DEFAULT_AREF: return new CBlender_deffer_aref(true); + case B_VERT: return new CBlender_deffer_flat(); + case B_VERT_AREF: return new CBlender_deffer_aref(false); + case B_SCREEN_SET: return new CBlender_Screen_SET(); + case B_SCREEN_GRAY: return 0; + case B_EDITOR_WIRE: return new CBlender_Editor_Wire(); + case B_EDITOR_SEL: return new CBlender_Editor_Selection(); + case B_LIGHT: return 0; + case B_LmBmmD: return new CBlender_BmmD(); + case B_LaEmB: return 0; + case B_LmEbB: return new CBlender_LmEbB(); + case B_B: return 0; + case B_BmmD: return new CBlender_BmmD(); + case B_SHADOW_TEX: return 0; + case B_SHADOW_WORLD: return 0; + case B_BLUR: return 0; + case B_MODEL: return new CBlender_deffer_model(); + case B_MODEL_EbB: return new CBlender_Model_EbB(); + case B_DETAIL: return new CBlender_Detail_Still(); + case B_TREE: return new CBlender_Tree(); + case B_PARTICLE: return new CBlender_Particle(); + } + return 0; +} + +void CRender::blender_destroy(IBlender* &B) +{ + xr_delete(B); +} diff --git a/src/Layers/xrRenderPC_GL/r2_sector_detect.cpp b/src/Layers/xrRenderPC_GL/r2_sector_detect.cpp new file mode 100644 index 00000000000..ec6f2d2d52d --- /dev/null +++ b/src/Layers/xrRenderPC_GL/r2_sector_detect.cpp @@ -0,0 +1,81 @@ +#include "stdafx.h" +#include "rgl.h" + +int CRender::translateSector(IRender_Sector* pSector) +{ + if (!pSector) + return -1; + + for (u32 i=0; iid; range1 = RP1->range; + } + } + + // Geometry model + int id2 = -1; + float range2 = range1; + Sectors_xrc.ray_query (g_pGameLevel->ObjectSpace.GetStaticModel(),P,dir,range2); + if (Sectors_xrc.r_count()) { + CDB::RESULT *RP2 = Sectors_xrc.r_begin(); + id2 = RP2->id; range2 = RP2->range; + } + + // Select ID + int ID; + if (id1>=0) { + if (id2>=0) ID = (range1<=range2+EPS)?id1:id2; // both was found + else ID = id1; // only id1 found + } else if (id2>=0) ID = id2; // only id2 found + else return 0; + + if (ID==id1) { + // Take sector, facing to our point from portal + CDB::TRI* pTri = rmPortals->get_tris() + ID; + CPortal* pPortal = (CPortal*) Portals[pTri->dummy]; + return pPortal->getSectorFacing(P); + } else { + // Take triangle at ID and use it's Sector + CDB::TRI* pTri = g_pGameLevel->ObjectSpace.GetStaticTris()+ID; + return getSector(pTri->sector); + } +} + diff --git a/src/Layers/xrRenderPC_GL/r2_types.h b/src/Layers/xrRenderPC_GL/r2_types.h new file mode 100644 index 00000000000..e8f2389b6bc --- /dev/null +++ b/src/Layers/xrRenderPC_GL/r2_types.h @@ -0,0 +1,101 @@ +#pragma once + + +// r3xx code-path (MRT) +#define r2_RT_depth "$user$depth" // MRT +#define r2_RT_MSAAdepth "$user$msaadepth" // MRT +#define r2_RT_P "$user$position" // MRT +#define r2_RT_N "$user$normal" // MRT +#define r2_RT_albedo "$user$albedo" // MRT + +// other +#define r2_RT_accum "$user$accum" // --- 16 bit fp or 16 bit fx +#define r2_RT_accum_temp "$user$accum_temp" // --- 16 bit fp - only for HW which doesn't feature fp16 blend + +#define r2_T_envs0 "$user$env_s0" // --- +#define r2_T_envs1 "$user$env_s1" // --- + +#define r2_T_sky0 "$user$sky0" +#define r2_T_sky1 "$user$sky1" + +#define r2_RT_ssao_temp "$user$ssao_temp" //temporary rt for ssao calculation +#define r2_RT_half_depth "$user$half_depth" //temporary rt for ssao calculation + +#define r2_RT_generic0 "$user$generic0" // --- +#define r2_RT_generic0_r "$user$generic0_r" // --- +#define r2_RT_generic1 "$user$generic1" // --- +#define r2_RT_generic1_r "$user$generic1_r" // --- +#define r2_RT_generic2 "$user$generic2" // --- // Igor: for volumetric lights +#define r2_RT_generic "$user$generic" // --- + +#define r2_RT_bloom1 "$user$bloom1" // --- +#define r2_RT_bloom2 "$user$bloom2" // --- + +#define r2_RT_luminance_t64 "$user$lum_t64" // --- temp +#define r2_RT_luminance_t8 "$user$lum_t8" // --- temp + +#define r2_RT_luminance_src "$user$tonemap_src" // --- prev-frame-result +#define r2_RT_luminance_cur "$user$tonemap" // --- result +#define r2_RT_luminance_pool "$user$luminance" // --- pool + +#define r2_RT_smap_surf "$user$smap_surf" // --- directional +#define r2_RT_smap_depth "$user$smap_depth" // ---directional +#define r2_RT_smap_depth_minmax "$user$smap_depth_minmax" + +#define r2_material "$user$material" // --- +#define r2_ds2_fade "$user$ds2_fade" // --- + +#define r2_jitter "$user$jitter_" // --- dither +#define r2_jitter_mipped "$user$jitter_mipped" // --- dither +#define r2_sunmask "sunmask" + +#define JITTER(a) r2_jitter #a + +const float SMAP_near_plane = .1f ; + +const u32 SMAP_adapt_min = 32 ; +const u32 SMAP_adapt_optimal = 768 ; +const u32 SMAP_adapt_max = 1536 ; + +const u32 TEX_material_LdotN = 128 ; // diffuse, X, almost linear = small res +const u32 TEX_material_LdotH = 256 ; // specular, Y +const u32 TEX_material_Count = 4 ; // Number of materials, Z +const u32 TEX_jitter = 64 ; +const u32 TEX_jitter_count = 5 ; // for HBAO + +const u32 BLOOM_size_X = 256 ; +const u32 BLOOM_size_Y = 256 ; +const u32 LUMINANCE_size = 16 ; + +// deffer +#define SE_R2_NORMAL_HQ 0 // high quality/detail +#define SE_R2_NORMAL_LQ 1 // low quality +#define SE_R2_SHADOW 2 // shadow generation + +// spot +#define SE_L_FILL 0 +#define SE_L_UNSHADOWED 1 +#define SE_L_NORMAL 2 // typical, scaled +#define SE_L_FULLSIZE 3 // full texture coverage +#define SE_L_TRANSLUENT 4 // with opacity/color mask + +// mask +#define SE_MASK_SPOT 0 +#define SE_MASK_POINT 1 +#define SE_MASK_DIRECT 2 +#define SE_MASK_ACCUM_VOL 3 +#define SE_MASK_ACCUM_2D 4 +#define SE_MASK_ALBEDO 5 + +// sun +#define SE_SUN_NEAR 0 +#define SE_SUN_FAR 1 +#define SE_SUN_LUMINANCE 2 +#define SE_SUN_NEAR_MINMAX 3 +// For rain R3 rendering +#define SE_SUN_RAIN_SMAP 3 + +extern float ps_r2_gloss_factor; +IC float u_diffuse2s (float x, float y, float z) { float v = (x+y+z)/3.f; return ps_r2_gloss_factor * ((v<1)?powf(v,2.f/3.f):v); } +IC float u_diffuse2s (Fvector3& c) { return u_diffuse2s(c.x,c.y,c.z); } + diff --git a/src/Layers/xrRenderPC_GL/rgl.cpp b/src/Layers/xrRenderPC_GL/rgl.cpp new file mode 100644 index 00000000000..ea7fe9ddaf2 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/rgl.cpp @@ -0,0 +1,632 @@ +#include "stdafx.h" +#include "rgl.h" +#include "../xrRender/fbasicvisual.h" +#include "glWallMarkArray.h" +#include "glUIShader.h" +#include "glRenderDeviceRender.h" + +CRender RImplementation; + +extern ENGINE_API BOOL r2_sun_static; +extern ENGINE_API BOOL r2_advanced_pp; // advanced post process and effects + +float r_dtex_range = 50.f; +////////////////////////////////////////////////////////////////////////// +ShaderElement* CRender::rimp_select_sh_dynamic(dxRender_Visual *pVisual, float cdist_sq) +{ + int id = SE_R2_SHADOW; + if (CRender::PHASE_NORMAL == RImplementation.phase) + { + id = ((_sqrt(cdist_sq) - pVisual->vis.sphere.R)shader->E[id]._get(); +} +////////////////////////////////////////////////////////////////////////// +ShaderElement* CRender::rimp_select_sh_static(dxRender_Visual *pVisual, float cdist_sq) +{ + int id = SE_R2_SHADOW; + if (CRender::PHASE_NORMAL == RImplementation.phase) + { + id = ((_sqrt(cdist_sq) - pVisual->vis.sphere.R)shader->E[id]._get(); +} +static class cl_parallax : public R_constant_setup { virtual void setup (R_constant* C) +{ + float h = ps_r2_df_parallax_h; + RCache.set_c (C,h,-h/2.f,1.f/r_dtex_range,1.f/r_dtex_range); +}} binder_parallax; + +static class cl_pos_decompress_params : public R_constant_setup { virtual void setup (R_constant* C) +{ + float VertTan = tanf( deg2rad(Device.fFOV/2.0f ) ); + float HorzTan = VertTan / Device.fASPECT; + + RCache.set_c ( C, HorzTan, VertTan, ( 2.0f * HorzTan )/(float)Device.dwWidth, ( 2.0f * VertTan ) /(float)Device.dwHeight ); + +}} binder_pos_decompress_params; + +static class cl_pos_decompress_params2 : public R_constant_setup { virtual void setup (R_constant* C) +{ + RCache.set_c (C,(float)Device.dwWidth, (float)Device.dwHeight, 1.0f/(float)Device.dwWidth, 1.0f/(float)Device.dwHeight ); + +}} binder_pos_decompress_params2; + +static class cl_water_intensity : public R_constant_setup +{ + virtual void setup (R_constant* C) + { + CEnvDescriptor& E = *g_pGamePersistent->Environment().CurrentEnv; + float fValue = E.m_fWaterIntensity; + RCache.set_c (C, fValue, fValue, fValue, 0); + } +} binder_water_intensity; + +static class cl_sun_shafts_intensity : public R_constant_setup +{ + virtual void setup (R_constant* C) + { + CEnvDescriptor& E = *g_pGamePersistent->Environment().CurrentEnv; + float fValue = E.m_fSunShaftsIntensity; + RCache.set_c (C, fValue, fValue, fValue, 0); + } +} binder_sun_shafts_intensity; + +void CRender::model_Delete(IRenderVisual* &V, BOOL bDiscard) +{ + dxRender_Visual* pVisual = (dxRender_Visual*)V; + Models->Delete(pVisual, bDiscard); + V = 0; +} + +IRender_DetailModel* CRender::model_CreateDM(IReader* F) +{ + CDetail* D = new CDetail(); + D->Load(F); + return D; +} + +void CRender::model_Delete(IRender_DetailModel* & F) +{ + if (F) + { + CDetail* D = (CDetail*)F; + D->Unload(); + xr_delete(D); + F = NULL; + } +} + +IRenderVisual* CRender::model_CreatePE(LPCSTR name) +{ + PS::CPEDef* SE = PSLibrary.FindPED(name); R_ASSERT3(SE, "Particle effect doesn't exist", name); + return Models->CreatePE(SE); +} + +IRenderVisual* CRender::model_CreateParticles(LPCSTR name) +{ + PS::CPEDef* SE = PSLibrary.FindPED(name); + if (SE) return Models->CreatePE(SE); + else{ + PS::CPGDef* SG = PSLibrary.FindPGD(name); R_ASSERT3(SG, "Particle effect or group doesn't exist", name); + return Models->CreatePG(SG); + } +} + +CRender::CRender() +{ +} + +CRender::~CRender() +{ +} + +void CRender::create() +{ + //Device.seqFrame.Add(this, REG_PRIORITY_HIGH + 0x12345678); + + m_skinning = -1; + m_MSAASample = -1; + + // hardware + o.smapsize = 2048; + o.mrt = TRUE; + o.mrtmixdepth = TRUE; + + // Check for NULL render target support + o.nullrt = false; + + // SMAP / DST + o.HW_smap_FETCH4 = FALSE; + o.HW_smap = true; + o.HW_smap_PCF = o.HW_smap; + if (o.HW_smap) + { + o.HW_smap_FORMAT = D3DFMT_D24X8; + Msg("* HWDST/PCF supported and used"); + } + + o.fp16_filter = true; + o.fp16_blend = true; + + if (o.mrtmixdepth) o.albedo_wo = FALSE; + else if (o.fp16_blend) o.albedo_wo = FALSE; + else o.albedo_wo = TRUE; + + // nvstencil on NV40 and up + o.nvstencil = FALSE; + if (strstr(Core.Params, "-nonvs")) o.nvstencil = FALSE; + + // nv-dbt + o.nvdbt = glewIsSupported("GL_EXT_depth_bounds_test"); + if (o.nvdbt) Msg("* NV-DBT supported and used"); + + // options (smap-pool-size) + if (strstr(Core.Params, "-smap1536")) o.smapsize = 1536; + if (strstr(Core.Params, "-smap2048")) o.smapsize = 2048; + if (strstr(Core.Params, "-smap2560")) o.smapsize = 2560; + if (strstr(Core.Params, "-smap3072")) o.smapsize = 3072; + if (strstr(Core.Params, "-smap4096")) o.smapsize = 4096; + + // gloss + char* g = strstr(Core.Params, "-gloss "); + o.forcegloss = g ? TRUE : FALSE; + if (g) { + o.forcegloss_v = float(atoi(g + xr_strlen("-gloss "))) / 255.f; + } + + // options + o.bug = (strstr(Core.Params, "-bug")) ? TRUE : FALSE; + o.sunfilter = (strstr(Core.Params, "-sunfilter")) ? TRUE : FALSE; + //. o.sunstatic = (strstr(Core.Params,"-sunstatic"))? TRUE :FALSE ; + o.sunstatic = r2_sun_static; + o.advancedpp = r2_advanced_pp; + //o.volumetricfog = ps_r2_ls_flags.test(R3FLAG_VOLUMETRIC_SMOKE); + o.sjitter = (strstr(Core.Params, "-sjitter")) ? TRUE : FALSE; + o.depth16 = (strstr(Core.Params, "-depth16")) ? TRUE : FALSE; + o.noshadows = (strstr(Core.Params, "-noshadows")) ? TRUE : FALSE; + o.Tshadows = (strstr(Core.Params, "-tsh")) ? TRUE : FALSE; + o.mblur = (strstr(Core.Params, "-mblur")) ? TRUE : FALSE; + o.distortion_enabled = (strstr(Core.Params, "-nodistort")) ? FALSE : TRUE; + o.distortion = o.distortion_enabled; + o.disasm = (strstr(Core.Params, "-disasm")) ? TRUE : FALSE; + o.forceskinw = (strstr(Core.Params, "-skinw")) ? TRUE : FALSE; + + o.ssao_blur_on = ps_r2_ls_flags_ext.test(R2FLAGEXT_SSAO_BLUR) && (ps_r_ssao != 0); + o.ssao_opt_data = ps_r2_ls_flags_ext.test(R2FLAGEXT_SSAO_OPT_DATA) && (ps_r_ssao != 0); + o.ssao_half_data = ps_r2_ls_flags_ext.test(R2FLAGEXT_SSAO_HALF_DATA) && o.ssao_opt_data && (ps_r_ssao != 0); + o.ssao_hdao = ps_r2_ls_flags_ext.test(R2FLAGEXT_SSAO_HDAO) && (ps_r_ssao != 0); + o.ssao_hbao = !o.ssao_hdao && ps_r2_ls_flags_ext.test(R2FLAGEXT_SSAO_HBAO) && (ps_r_ssao != 0); + + + // constants + glRenderDeviceRender::Instance().Resources->RegisterConstantSetup("parallax", &binder_parallax); + glRenderDeviceRender::Instance().Resources->RegisterConstantSetup("water_intensity", &binder_water_intensity); + glRenderDeviceRender::Instance().Resources->RegisterConstantSetup("sun_shafts_intensity", &binder_sun_shafts_intensity); + glRenderDeviceRender::Instance().Resources->RegisterConstantSetup("pos_decompression_params", &binder_pos_decompress_params); + + c_lmaterial = "L_material"; + c_sbase = "s_base"; + + Target = new CRenderTarget(); // Main target + + Models = new CModelPool(); + PSLibrary.OnCreate(); + HWOCC.occq_create(occq_size); + + rmNormal (); + marker = 0; + //R_CHK (HW.pDevice->CreateQuery(D3DQUERYTYPE_EVENT,&q_sync_point[0])); + //R_CHK (HW.pDevice->CreateQuery(D3DQUERYTYPE_EVENT,&q_sync_point[1])); + ZeroMemory(q_sync_point, sizeof(q_sync_point)); + + xrRender_apply_tf(); + ::PortalTraverser.initialize(); +} + +void CRender::LoadIncludes(LPCSTR pSrcData, UINT SrcDataLen, xr_vector& source, xr_vector& includes) +{ + char* srcData = xr_alloc(SrcDataLen + 2); + memcpy(srcData, pSrcData, SrcDataLen); + srcData[SrcDataLen] = '\n'; + srcData[SrcDataLen + 1] = '\0'; + includes.push_back(srcData); + source.push_back(srcData); + + string_path path; + char* str = srcData; + while (strstr(str, "#include") != nullptr) + { + // Get filename of include directive + str = strstr(str, "#include"); // Find the include directive + char* fn = strchr(str, '"') + 1; // Get filename, skip quotation + *str = '\0'; // Terminate previous source + str = strchr(fn, '"'); // Get end of filename path + *str = '\0'; // Terminate filename path + + // Create path to included shader + strconcat(sizeof(path), path, ::Render->getShaderPath(), fn); + FS.update_path(path, "$game_shaders$", path); + while (char* sep = strchr(path, '/')) *sep = '\\'; + + // Open and read file, recursively load includes + IReader* R = FS.r_open(path); + R_ASSERT2(R, path); + LoadIncludes((char*)R->pointer(), R->length(), source, includes); + FS.r_close(R); + + // Add next source, skip quotation + str++; + source.push_back(str); + } +} + +struct SHADER_MACRO { + char *Define = "#define ", *Name = "\n", *Sep = "\t", *Definition = "\n", *EOL = "\n"; +}; + +HRESULT CRender::shader_compile( + LPCSTR name, + LPCSTR pSrcData, + UINT SrcDataLen, + void* _pDefines, + void* _pInclude, + LPCSTR pFunctionName, + LPCSTR pTarget, + DWORD Flags, + void* _ppShader, + void* _ppErrorMsgs, + void* _ppConstantTable) +{ + xr_vector source, includes; + SHADER_MACRO defines[128]; + int def_it = 0; + char c_smapsize[32]; + char c_gloss[32]; + char c_sun_shafts[32]; + char c_ssao[32]; + char c_sun_quality[32]; + + // TODO: OGL: Implement these parameters. + VERIFY(!_pDefines); + VERIFY(!_pInclude); + VERIFY(!pFunctionName); + VERIFY(!pTarget); + VERIFY(!Flags); + VERIFY(!_ppConstantTable); + + // open included files + LoadIncludes(pSrcData, SrcDataLen, source, includes); + + // options + { + sprintf(c_smapsize, "%d", u32(o.smapsize)); + defines[def_it].Name = "SMAP_size"; + defines[def_it].Definition = c_smapsize; + def_it++; + } + if (o.fp16_filter) { + defines[def_it].Name = "FP16_FILTER"; + defines[def_it].Definition = "1"; + def_it++; + } + if (o.fp16_blend) { + defines[def_it].Name = "FP16_BLEND"; + defines[def_it].Definition = "1"; + def_it++; + } + if (o.HW_smap) { + defines[def_it].Name = "USE_HWSMAP"; + defines[def_it].Definition = "1"; + def_it++; + } + if (o.HW_smap_PCF) { + defines[def_it].Name = "USE_HWSMAP_PCF"; + defines[def_it].Definition = "1"; + def_it++; + } + if (o.HW_smap_FETCH4) { + defines[def_it].Name = "USE_FETCH4"; + defines[def_it].Definition = "1"; + def_it++; + } + if (o.sjitter) { + defines[def_it].Name = "USE_SJITTER"; + defines[def_it].Definition = "1"; + def_it++; + } + if (o.Tshadows) { + defines[def_it].Name = "USE_TSHADOWS"; + defines[def_it].Definition = "1"; + def_it++; + } + if (o.mblur) { + defines[def_it].Name = "USE_MBLUR"; + defines[def_it].Definition = "1"; + def_it++; + } + if (o.sunfilter) { + defines[def_it].Name = "USE_SUNFILTER"; + defines[def_it].Definition = "1"; + def_it++; + } + if (o.sunstatic) { + defines[def_it].Name = "USE_R2_STATIC_SUN"; + defines[def_it].Definition = "1"; + def_it++; + } + if (o.forcegloss) { + sprintf(c_gloss, "%f", o.forcegloss_v); + defines[def_it].Name = "FORCE_GLOSS"; + defines[def_it].Definition = c_gloss; + def_it++; + } + if (o.forceskinw) { + defines[def_it].Name = "SKIN_COLOR"; + defines[def_it].Definition = "1"; + def_it++; + } + + if (o.ssao_blur_on) + { + defines[def_it].Name = "USE_SSAO_BLUR"; + defines[def_it].Definition = "1"; + def_it++; + } + + if (o.ssao_opt_data) + { + defines[def_it].Name = "SSAO_OPT_DATA"; + if (o.ssao_half_data) + defines[def_it].Definition = "2"; + else + defines[def_it].Definition = "1"; + def_it++; + } + + if (o.ssao_hdao) + { + defines[def_it].Name = "HDAO"; + defines[def_it].Definition = "1"; + def_it++; + } + + if (o.ssao_hbao) + { + defines[def_it].Name = "USE_HBAO"; + defines[def_it].Definition = "1"; + def_it++; + } + + // skinning + if (m_skinning<0) { + defines[def_it].Name = "SKIN_NONE"; + defines[def_it].Definition = "1"; + def_it++; + } + if (0 == m_skinning) { + defines[def_it].Name = "SKIN_0"; + defines[def_it].Definition = "1"; + def_it++; + } + if (1 == m_skinning) { + defines[def_it].Name = "SKIN_1"; + defines[def_it].Definition = "1"; + def_it++; + } + if (2 == m_skinning) { + defines[def_it].Name = "SKIN_2"; + defines[def_it].Definition = "1"; + def_it++; + } + if (3 == m_skinning) { + defines[def_it].Name = "SKIN_3"; + defines[def_it].Definition = "1"; + def_it++; + } + if (4 == m_skinning) { + defines[def_it].Name = "SKIN_4"; + defines[def_it].Definition = "1"; + def_it++; + } + R_ASSERT(m_skinning < 5); + + // Igor: need restart options + if (RImplementation.o.advancedpp && ps_r2_ls_flags.test(R2FLAG_SOFT_WATER)) + { + defines[def_it].Name = "USE_SOFT_WATER"; + defines[def_it].Definition = "1"; + def_it++; + } + + if (RImplementation.o.advancedpp && ps_r2_ls_flags.test(R2FLAG_SOFT_PARTICLES)) + { + defines[def_it].Name = "USE_SOFT_PARTICLES"; + defines[def_it].Definition = "1"; + def_it++; + } + + if (RImplementation.o.advancedpp && ps_r2_ls_flags.test(R2FLAG_DOF)) + { + defines[def_it].Name = "USE_DOF"; + defines[def_it].Definition = "1"; + def_it++; + } + + if (RImplementation.o.advancedpp && ps_r_sun_shafts) + { + sprintf_s(c_sun_shafts, "%d", ps_r_sun_shafts); + defines[def_it].Name = "SUN_SHAFTS_QUALITY"; + defines[def_it].Definition = c_sun_shafts; + def_it++; + } + + if (RImplementation.o.advancedpp && ps_r_ssao) + { + sprintf_s(c_ssao, "%d", ps_r_ssao); + defines[def_it].Name = "SSAO_QUALITY"; + defines[def_it].Definition = c_ssao; + def_it++; + } + + if (RImplementation.o.advancedpp && ps_r_sun_quality) + { + sprintf_s(c_sun_quality, "%d", ps_r_sun_quality); + defines[def_it].Name = "SUN_QUALITY"; + defines[def_it].Definition = c_sun_quality; + def_it++; + } + + if (RImplementation.o.advancedpp && ps_r2_ls_flags.test(R2FLAG_STEEP_PARALLAX)) + { + defines[def_it].Name = "ALLOW_STEEPPARALLAX"; + defines[def_it].Definition = "1"; + def_it++; + } + + // Compile sources list + size_t def_len = def_it * 5; + size_t sources_len = source.size() + def_len + 2; + string256 name_comment; + sprintf_s(name_comment, "// %s\n", name); + const char** sources = xr_alloc(sources_len); + sources[0] = "#version 410\n"; + sources[1] = name_comment; + memcpy(sources + 2, defines, def_len * sizeof(char*)); + memcpy(sources + def_len + 2, source.data(), source.size() * sizeof(char*)); + + // Compile the shader + GLuint shader = *(GLuint*)_ppShader; + R_ASSERT(shader); + CHK_GL(glShaderSource(shader, sources_len, sources, nullptr)); + CHK_GL(glCompileShader(shader)); + + // Create the shader program + GLuint program = glCreateProgram(); + R_ASSERT(program); + CHK_GL(glObjectLabel(GL_PROGRAM, program, -1, name)); + CHK_GL(glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE)); + *(GLuint*)_ppShader = program; + + // Free string resources + xr_free(sources); + for (xr_vector::iterator it = includes.begin(); it != includes.end(); it++) + xr_free(*it); + + // Get the compilation result + GLint result; + CHK_GL(glGetShaderiv(shader, GL_COMPILE_STATUS, &result)); + + // Link program if compilation succeeded + if (result) { + CHK_GL(glAttachShader(program, shader)); + CHK_GL(glLinkProgram(program)); + CHK_GL(glDetachShader(program, shader)); + CHK_GL(glGetProgramiv(program, GL_LINK_STATUS, &result)); + + if (_ppErrorMsgs) + { + // Get the compilation log, if requested + GLint length; + GLchar** _pErrorMsgs = (GLchar**)_ppErrorMsgs; + CHK_GL(glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length)); + *_pErrorMsgs = xr_alloc(length); + CHK_GL(glGetProgramInfoLog(program, length, nullptr, *_pErrorMsgs)); + } + } + else if (_ppErrorMsgs) + { + // Get the compilation log, if requested + GLint length; + GLchar** _pErrorMsgs = (GLchar**)_ppErrorMsgs; + CHK_GL(glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length)); + *_pErrorMsgs = xr_alloc(length); + CHK_GL(glGetShaderInfoLog(shader, length, nullptr, *_pErrorMsgs)); + } + + CHK_GL(glDeleteShader(shader)); + return result; +} + +void CRender::reset_begin() +{ + // Update incremental shadowmap-visibility solver + // BUG-ID: 10646 + { + u32 it = 0; + for (it = 0; itsvis.resetoccq(); + } + catch (...) + { + Msg("! Failed to flush-OCCq on light [%d] %X", it, *(u32*)(&Lights_LastFrame[it])); + } + } + Lights_LastFrame.clear(); + } + + xr_delete(Target); + HWOCC.occq_destroy(); +} + +void CRender::reset_end() +{ + HWOCC.occq_create(occq_size); + Target = new CRenderTarget(); + xrRender_apply_tf(); +} + +void CRender::rmNear() +{ + IRender_Target* T = getTarget(); + CHK_GL(glViewport(0, 0, T->get_width(), T->get_height())); + CHK_GL(glDepthRangef(0.f, 0.02f)); +} + +void CRender::rmFar() +{ + IRender_Target* T = getTarget(); + CHK_GL(glViewport(0, 0, T->get_width(), T->get_height())); + CHK_GL(glDepthRangef(0.99999f, 1.f)); +} + +void CRender::rmNormal() +{ + IRender_Target* T = getTarget(); + CHK_GL(glViewport(0, 0, T->get_width(), T->get_height())); + CHK_GL(glDepthRangef(0.f, 1.f)); +} + +void CRender::add_StaticWallmark(ref_shader& S, const Fvector& P, float s, CDB::TRI* T, Fvector* verts) +{ + if (T->suppress_wm) return; + VERIFY2(_valid(P) && _valid(s) && T && verts && (s>EPS_L), "Invalid static wallmark params"); + Wallmarks->AddStaticWallmark(T, verts, P, &*S, s); +} + +void CRender::add_StaticWallmark(IWallMarkArray *pArray, const Fvector& P, float s, CDB::TRI* T, Fvector* V) +{ + glWallMarkArray *pWMA = (glWallMarkArray *)pArray; + ref_shader *pShader = pWMA->glGenerateWallmark(); + if (pShader) add_StaticWallmark(*pShader, P, s, T, V); +} + +void CRender::add_StaticWallmark(const wm_shader& S, const Fvector& P, float s, CDB::TRI* T, Fvector* V) +{ + glUIShader* pShader = (glUIShader*)&*S; + add_StaticWallmark(pShader->hShader, P, s, T, V); +} + +void CRender::add_SkeletonWallmark(const Fmatrix* xf, CKinematics* obj, ref_shader& sh, const Fvector& start, const Fvector& dir, float size) +{ + Wallmarks->AddSkeletonWallmark(xf, obj, sh, start, dir, size); +} + +void CRender::add_SkeletonWallmark(const Fmatrix* xf, IKinematics* obj, IWallMarkArray *pArray, const Fvector& start, const Fvector& dir, float size) +{ + glWallMarkArray *pWMA = (glWallMarkArray *)pArray; + ref_shader *pShader = pWMA->glGenerateWallmark(); + if (pShader) add_SkeletonWallmark(xf, (CKinematics*)obj, *pShader, start, dir, size); +} diff --git a/src/Layers/xrRenderPC_GL/rgl.h b/src/Layers/xrRenderPC_GL/rgl.h new file mode 100644 index 00000000000..cf79ad580b5 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/rgl.h @@ -0,0 +1,347 @@ +#pragma once + +#include "../xrRender/r__dsgraph_structure.h" +#include "../xrRender/r__occlusion.h" + +#include "../xrRender/PSLibrary.h" + +#include "r2_types.h" +#include "gl_rendertarget.h" +#include "glRenderDeviceRender.h" + +#include "../xrRender/hom.h" +#include "../xrRender/detailmanager.h" +#include "../xrRender/modelpool.h" +#include "../xrRender/wallmarksengine.h" + +#include "smap_allocator.h" +#include "../xrRender/light_db.h" +#include "../xrRender/light_render_direct.h" +#include "../xrRender/LightTrack.h" + +#include "../xrRender/SkeletonCustom.h" +#include "../../xrEngine/irenderable.h" +#include "../../xrEngine/fmesh.h" + +#define HW RImplementation + +class CGlow : public IRender_Glow +{ +public: + bool bActive; +public: + CGlow() : bActive(false) { } + virtual void set_active(bool b) { bActive = b; } + virtual bool get_active() { return bActive; } + virtual void set_position(const Fvector& P) { } + virtual void set_direction(const Fvector& D) { } + virtual void set_radius(float R) { } + virtual void set_texture(LPCSTR name) { } + virtual void set_color(const Fcolor& C) { } + virtual void set_color(float r, float g, float b) { } +}; + +class CRender : public R_dsgraph_structure +{ +public: + enum + { + PHASE_NORMAL = 0, // E[0] + PHASE_SMAP = 1, // E[1] + }; + + struct _options { + u32 bug : 1; + + u32 ssao_blur_on : 1; + u32 ssao_opt_data : 1; + u32 ssao_half_data : 1; + u32 ssao_hbao : 1; + u32 ssao_hdao : 1; + + u32 smapsize : 16; + u32 depth16 : 1; + u32 mrt : 1; + u32 mrtmixdepth : 1; + u32 fp16_filter : 1; + u32 fp16_blend : 1; + u32 albedo_wo : 1; // work-around albedo on less capable HW + u32 HW_smap : 1; + u32 HW_smap_PCF : 1; + u32 HW_smap_FETCH4 : 1; + + u32 HW_smap_FORMAT : 32; + + u32 nvstencil : 1; + u32 nvdbt : 1; + + u32 nullrt : 1; + + u32 distortion : 1; + u32 distortion_enabled : 1; + u32 mblur : 1; + + u32 sunfilter : 1; + u32 sunstatic : 1; + u32 sjitter : 1; + u32 noshadows : 1; + u32 Tshadows : 1; // transluent shadows + u32 disasm : 1; + u32 advancedpp : 1; // advanced post process (DOF, SSAO, volumetrics, etc.) + + u32 forcegloss : 1; + u32 forceskinw : 1; + float forcegloss_v; + } o; + struct _stats { + u32 l_total, l_visible; + u32 l_shadowed, l_unshadowed; + s32 s_used, s_merged, s_finalclip; + u32 o_queries, o_culled; + u32 ic_total, ic_culled; + } stats; +public: + // Sector detection and visibility + CSector* pLastSector; + Fvector vLastCameraPos; + u32 uLastLTRACK; + xr_vector Portals; + xr_vector Sectors; + xrXRC Sectors_xrc; + CDB::MODEL* rmPortals; + CHOM HOM; + R_occlusion HWOCC; + + // Global vertex-buffer container + typedef svector VertexDeclarator; + xr_vector SWIs; + xr_vector Shaders; + xr_vector nDC, xDC; + xr_vector nVB, xVB; + xr_vector nIB, xIB; + xr_vector Visuals; + CPSLibrary PSLibrary; + + CDetailManager* Details; + CModelPool* Models; + CWallmarksEngine* Wallmarks; + + CRenderTarget* Target; // Render-target + + CLight_DB Lights; + CLight_Compute_XFORM_and_VIS LR; + xr_vector Lights_LastFrame; + SMAP_Allocator LP_smap_pool; + light_Package LP_normal; + light_Package LP_pending; + + xr_vector > main_coarse_structure; + + shared_str c_sbase; + shared_str c_lmaterial; + float o_hemi; + float o_hemi_cube[CROS_impl::NUM_FACES]; + float o_sun; + GLsync q_sync_point[CHWCaps::MAX_GPUS]; + u32 q_sync_count; + + // HW Support + GLuint pBaseZB; + CHWCaps Caps; + glRenderDeviceRender* pDevice; + +private: + // Loading / Unloading + void LoadBuffers(CStreamReader *fs, BOOL _alternative); + void LoadVisuals(IReader *fs); + void LoadLights(IReader *fs); + void LoadPortals(IReader *fs); + void LoadSectors(IReader *fs); + void LoadSWIs(CStreamReader *fs); + void LoadIncludes(LPCSTR pSrcData, UINT SrcDataLen, xr_vector& source, xr_vector& includes); + +public: + ShaderElement* rimp_select_sh_static(dxRender_Visual *pVisual, float cdist_sq); + ShaderElement* rimp_select_sh_dynamic(dxRender_Visual *pVisual, float cdist_sq); + IRender_Portal* getPortal(int id) { VERIFY(idrenderable_ROS()) return; + CROS_impl& LT = *((CROS_impl*)O->renderable_ROS()); + LT.update_smooth(O); + o_hemi = 0.75f*LT.get_hemi(); + //o_hemi = 0.5f*LT.get_hemi () ; + o_sun = 0.75f*LT.get_sun(); + CopyMemory(o_hemi_cube, LT.get_hemi_cube(), CROS_impl::NUM_FACES*sizeof(float)); + } + IC void apply_lmaterial() + { + R_constant* C = &*RCache.get_c(c_sbase); // get sampler + if (0 == C) return; + VERIFY(RC_dest_sampler == C->destination); + VERIFY(RC_sampler == C->type); + CTexture* T = RCache.get_ActiveTexture(u32(C->samp.index)); + VERIFY(T); + float mtl = T->m_material; +#ifdef DEBUG + if (ps_r2_ls_flags.test(R2FLAG_GLOBALMATERIAL)) mtl = ps_r2_gmaterial; +#endif + RCache.hemi.set_material(o_hemi, o_sun, 0, (mtl + .5f) / 4.f); + RCache.hemi.set_pos_faces(o_hemi_cube[CROS_impl::CUBE_FACE_POS_X], + o_hemi_cube[CROS_impl::CUBE_FACE_POS_Y], + o_hemi_cube[CROS_impl::CUBE_FACE_POS_Z]); + RCache.hemi.set_neg_faces(o_hemi_cube[CROS_impl::CUBE_FACE_NEG_X], + o_hemi_cube[CROS_impl::CUBE_FACE_NEG_Y], + o_hemi_cube[CROS_impl::CUBE_FACE_NEG_Z]); + } + +private: + BOOL add_Dynamic(dxRender_Visual*pVisual, u32 planes); // normal processing + void add_Static(dxRender_Visual*pVisual, u32 planes); + void add_leafs_Dynamic(dxRender_Visual*pVisual); // if detected node's full visibility + void add_leafs_Static(dxRender_Visual*pVisual); // if detected node's full visibility + +public: + IRender_Sector* rimp_detectSector(Fvector& P, Fvector& D); + void render_main(Fmatrix& mCombined, bool _fportals); + void render_forward(); + void render_smap_direct(Fmatrix& mCombined); + void render_indirect(light* L); + void render_lights(light_Package& LP); + void render_sun(); + void render_sun_near(); + void render_sun_filtered(); + void render_menu(); + +public: + // feature level + virtual GenerationLevel get_generation() { return IRender_interface::GENERATION_R2; }; + + virtual bool is_sun_static() { return o.sunstatic; }; + virtual DWORD get_dx_level() { return 0x00000000; }; + + // Loading / Unloading + virtual void create(); + virtual void destroy() { VERIFY(!"CRender::destroy not implemented."); }; + virtual void reset_begin(); + virtual void reset_end(); + + virtual void level_Load(IReader*); + virtual void level_Unload(); + + virtual GLuint texture_load(LPCSTR fname, u32& msize, GLenum& desc); + virtual HRESULT shader_compile( + LPCSTR name, + LPCSTR pSrcData, + UINT SrcDataLen, + void* pDefines, + void* pInclude, + LPCSTR pFunctionName, + LPCSTR pTarget, + DWORD Flags, + void* ppShader, + void* ppErrorMsgs, + void* ppConstantTable); + + // Information + virtual void Statistics(CGameFont* F) { VERIFY(!"CRender::Statistics not implemented."); }; + + virtual LPCSTR getShaderPath() { return "gl\\"; } + virtual ref_shader getShader(int id) { VERIFY(idgetMask()); }; // add visual(s) (all culling performed) + + // Wallmarks + virtual void add_StaticWallmark(ref_shader& S, const Fvector& P, float s, CDB::TRI* T, Fvector* V); + virtual void add_StaticWallmark(const wm_shader& S, const Fvector& P, float s, CDB::TRI* T, Fvector* V); + virtual void add_StaticWallmark(IWallMarkArray *pArray, const Fvector& P, float s, CDB::TRI* T, Fvector* V); + virtual void clear_static_wallmarks() { Wallmarks->clear(); }; + virtual void add_SkeletonWallmark(intrusive_ptr wm) { Wallmarks->AddSkeletonWallmark(wm); }; + virtual void add_SkeletonWallmark(const Fmatrix* xf, CKinematics* obj, ref_shader& sh, const Fvector& start, const Fvector& dir, float size); + virtual void add_SkeletonWallmark(const Fmatrix* xf, IKinematics* obj, IWallMarkArray *pArray, const Fvector& start, const Fvector& dir, float size); + + // + virtual IBlender* blender_create(CLASS_ID cls); + virtual void blender_destroy(IBlender* &); + + virtual IRender_ObjectSpecific* ros_create(IRenderable* parent) { return new CROS_impl(); }; + virtual void ros_destroy(IRender_ObjectSpecific* &p) { xr_delete(p); }; + + // Lighting/glowing + virtual IRender_Light* light_create() { return Lights.Create(); }; + virtual IRender_Glow* glow_create() { return new CGlow(); }; + + // Models + virtual IRenderVisual* model_CreateParticles(LPCSTR name); + virtual IRender_DetailModel* model_CreateDM(IReader* F); + IRenderVisual* model_Create(LPCSTR name, IReader* data) { return Models->Create(name,data); } + IRenderVisual* model_CreateChild(LPCSTR name, IReader* data) { return Models->CreateChild(name,data);} + IRenderVisual* model_Duplicate(IRenderVisual* V) { return Models->Instance_Duplicate((dxRender_Visual*)V); } + virtual void model_Delete(IRenderVisual* & V, BOOL bDiscard = FALSE); + virtual void model_Delete(IRender_DetailModel* & F); + virtual void model_Logging(BOOL bEnable) { Models->Logging(bEnable); } + virtual void models_Prefetch() { Models->Prefetch(); } + virtual void models_Clear(BOOL b_complete) { Models->ClearPool(b_complete); } + IRenderVisual* model_CreatePE(LPCSTR name); + + // Occlusion culling + virtual BOOL occ_visible(vis_data& V) { return HOM.visible(V); }; + virtual BOOL occ_visible(Fbox& B) { return HOM.visible(B); }; + virtual BOOL occ_visible(sPoly& P) { return HOM.visible(P); }; + + // Main + virtual void Calculate(); + virtual void Render(); + + virtual void Screenshot(ScreenshotMode mode = SM_NORMAL, LPCSTR name = 0) { VERIFY(!"CRender::Screenshot not implemented."); }; + virtual void Screenshot(ScreenshotMode mode, CMemoryWriter& memory_writer) { VERIFY(!"CRender::Screenshot not implemented."); }; + virtual void ScreenshotAsyncBegin() { VERIFY(!"CRender::ScreenshotAsyncBegin not implemented."); }; + virtual void ScreenshotAsyncEnd(CMemoryWriter& memory_writer) { VERIFY(!"CRender::ScreenshotAsyncEnd not implemented."); }; + virtual void OnFrame() { VERIFY(!"CRender::OnFrame not implemented."); }; + + // Render mode + virtual void rmNear(); + virtual void rmFar(); + virtual void rmNormal(); + virtual u32 memory_usage() { VERIFY(!"CRender::memory_usage not implemented."); return 0; }; + + // Constructor/destructor + CRender(); + virtual ~CRender(); +protected: + virtual void ScreenshotImpl(ScreenshotMode mode, LPCSTR name, CMemoryWriter* memory_writer) { VERIFY(!"CRender::ScreenshotImpl not implemented."); }; +}; + +extern CRender RImplementation; diff --git a/src/Layers/xrRenderPC_GL/stdafx.cpp b/src/Layers/xrRenderPC_GL/stdafx.cpp new file mode 100644 index 00000000000..bf4bbe2e33b --- /dev/null +++ b/src/Layers/xrRenderPC_GL/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// xrRender_GL.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/src/Layers/xrRenderPC_GL/stdafx.h b/src/Layers/xrRenderPC_GL/stdafx.h new file mode 100644 index 00000000000..4b7d63d71a4 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/stdafx.h @@ -0,0 +1,58 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently + +#pragma once + +#pragma warning(disable:4995) +#include "xrEngine/stdafx.h" +#pragma warning(default:4995) +#pragma warning(disable:4714) +#pragma warning( 4 : 4018 ) +#pragma warning( 4 : 4244 ) +#pragma warning(disable:4237) + +#define GLEW_STATIC +#include +#include +#include +#include +#include + +// TODO: Get rid of D3D types. +#include + +#define R_GL 0 +#define R_R1 1 +#define R_R2 2 +#define R_R3 3 +#define RENDER R_GL + +#include "xrParticles/psystem.h" + +#include "Layers/xrRender/HW.h" +#include "Layers/xrRender/Shader.h" +#include "Layers/xrRender/R_Backend.h" +#include "Layers/xrRender/R_Backend_Runtime.h" + +#include "Layers/xrRender/ResourceManager.h" + +#include "xrEngine/vis_common.h" +#include "xrEngine/Render.h" +#include "Common/_d3d_extensions.h" +#include "xrEngine/IGame_Level.h" +#include "Layers/xrRender/blenders\blender.h" +#include "Layers/xrRender/blenders\blender_clsid.h" +#include "Layers/xrRender/xrRender_console.h" +#include "rgl.h" + +IC void jitter(CBlender_Compile& C) +{ + C.r_Sampler("jitter0", JITTER(0), true, D3DTADDRESS_WRAP, D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_POINT); + C.r_Sampler("jitter1", JITTER(1), true, D3DTADDRESS_WRAP, D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_POINT); + C.r_Sampler("jitter2", JITTER(2), true, D3DTADDRESS_WRAP, D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_POINT); + C.r_Sampler("jitter3", JITTER(3), true, D3DTADDRESS_WRAP, D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_POINT); + C.r_Sampler("jitter4", JITTER(4), true, D3DTADDRESS_WRAP, D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_POINT); +} + +class glState; diff --git a/src/Layers/xrRenderPC_GL/xrRender_GL.cpp b/src/Layers/xrRenderPC_GL/xrRender_GL.cpp new file mode 100644 index 00000000000..950d67b5cf2 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/xrRender_GL.cpp @@ -0,0 +1,36 @@ +// xrRender_GL.cpp : Defines the entry point for the DLL application. +// +#include "stdafx.h" +#include "glRenderFactory.h" +#include "glUIRender.h" +#include "glDebugRender.h" + +#pragma comment(lib,"xrEngine.lib") + +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH : + // Can't call CreateDXGIFactory from DllMain + //if (!xrRender_test_hw()) return FALSE; + ::Render = &RImplementation; + ::RenderFactory = &RenderFactoryImpl; + ::DU = &DUImpl; + //::vid_mode_token = filled by glRenderDeviceRender + UIRender = &UIRenderImpl; +#ifdef DEBUG + DRender = &DebugRenderImpl; +#endif // DEBUG + xrRender_initconsole (); + break ; + case DLL_THREAD_ATTACH : + case DLL_THREAD_DETACH : + case DLL_PROCESS_DETACH : + break; + } + return TRUE; +} diff --git a/src/Layers/xrRenderPC_GL/xrRender_GL.vcxproj b/src/Layers/xrRenderPC_GL/xrRender_GL.vcxproj new file mode 100644 index 00000000000..34f37f5af53 --- /dev/null +++ b/src/Layers/xrRenderPC_GL/xrRender_GL.vcxproj @@ -0,0 +1,543 @@ + + + + + Debug + Win32 + + + Mixed + Win32 + + + Release + Win32 + + + + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6} + xrRender_GL + Win32Proj + + + + DynamicLibrary + v140 + MultiByte + + + DynamicLibrary + v140 + MultiByte + true + + + DynamicLibrary + v140 + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>12.0.30501.0 + + + $(SolutionDir)binaries\$(Configuration)\ + $(SolutionDir)intermediate\$(Configuration)\$(ProjectName)\ + true + true + + + $(SolutionDir)binaries\$(Configuration)\ + $(SolutionDir)intermediate\$(Configuration)\$(ProjectName)\ + false + + + $(SolutionDir)binaries\$(Configuration)\ + $(SolutionDir)intermediate\$(Configuration)\$(ProjectName)\ + false + + + + Disabled + true + .\;$(DXSDK_DIR)\include;$(SolutionDir)engine;$(SolutionDir)sdk\include;$(SolutionDir)3rd party;$(SolutionDir)3rd party\glew\include;$(SolutionDir)3rd party\gli;$(SolutionDir)3rd party\gli\external\glm;$(AdditionalIncludeDirectories);%(AdditionalIncludeDirectories) + USE_OGL;NO_XR_VDECLARATOR;WIN32;DEBUG;_WINDOWS;_USRDLL;XRRENDER_GL_EXPORTS;_SECURE_SCL=0;%(PreprocessorDefinitions) + false + Sync + EnableFastChecks + true + MultiThreadedDLL + true + Fast + false + true + Use + $(IntDir)$(ProjectName).pch + $(IntDir) + $(IntDir) + $(IntDir) + Level4 + ProgramDatabase + true + + + opengl32.lib;glu32.lib;glew32.lib;%(AdditionalDependencies) + true + $(DXSDK_DIR)\Lib\x86;$(SolutionDir)sdk\libraries;$(SolutionDir)libraries\$(Configuration);$(AdditionalLibraryDirectories) + true + false + + Windows + true + $(SolutionDir)libraries\$(Configuration)\$(TargetName).lib + MachineX86 + false + + + + + MaxSpeed + AnySuitable + true + Speed + true + true + true + .\;$(DXSDK_DIR)\include;$(SolutionDir)engine;$(SolutionDir)sdk\include;$(SolutionDir)3rd party;$(SolutionDir)3rd party\glew\include;$(SolutionDir)3rd party\gli;$(SolutionDir)3rd party\gli\external\glm;$(AdditionalIncludeDirectories);%(AdditionalIncludeDirectories) + USE_OGL;NO_XR_VDECLARATOR;WIN32;NDEBUG;_WINDOWS;_USRDLL;XRRENDER_GL_EXPORTS;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + + MultiThreadedDLL + false + false + StreamingSIMDExtensions + Fast + false + true + Use + $(IntDir)$(ProjectName).pch + + $(IntDir) + $(IntDir) + $(IntDir) + Level4 + ProgramDatabase + true + + + opengl32.lib;glu32.lib;glew32.lib;%(AdditionalDependencies) + $(DXSDK_DIR)\Lib\x86;$(SolutionDir)sdk\libraries;$(SolutionDir)libraries\$(Configuration);$(AdditionalLibraryDirectories) + true + $(OutDir)$(TargetName).pdb + false + + NotSet + true + true + true + UseLinkTimeCodeGeneration + $(SolutionDir)libraries\$(Configuration)\$(TargetName).lib + MachineX86 + false + + + + + Full + AnySuitable + true + Speed + false + true + .\;$(DXSDK_DIR)\include;$(SolutionDir)engine;$(SolutionDir)sdk\include;$(SolutionDir)3rd party;$(SolutionDir)3rd party\glew\include;$(SolutionDir)3rd party\gli;$(SolutionDir)3rd party\gli\external\glm;$(AdditionalIncludeDirectories);%(AdditionalIncludeDirectories) + USE_OGL;NO_XR_VDECLARATOR;MIXED;WIN32;DEBUG;_WINDOWS;_USRDLL;XRRENDER_GL_EXPORTS;_SECURE_SCL=0;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + false + Fast + false + true + Use + $(IntDir)$(ProjectName).pch + + $(IntDir) + $(IntDir) + $(IntDir) + Level4 + ProgramDatabase + true + + + opengl32.lib;glu32.lib;glew32.lib;%(AdditionalDependencies) + $(DXSDK_DIR)\Lib\x86;$(SolutionDir)sdk\libraries;$(SolutionDir)libraries\$(Configuration);$(AdditionalLibraryDirectories) + true + false + $(OutDir)$(TargetName).map + Windows + true + $(SolutionDir)libraries\$(Configuration)\$(TargetName).lib + MachineX86 + false + + + + + + + + + + + + + + + + + + + + + Level2 + Level2 + Level2 + + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + $(IntDir)%(Filename)1.xdc + $(IntDir)%(Filename)1.xdc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {a0f7d1fb-59a7-4717-a7e4-96f37e91998e} + + + {2578c6d8-660d-48ae-9322-7422f8664f06} + + + {94a1c366-3d19-48e6-8170-4adc2e70df97} + + + {132c62de-de85-4978-9675-c78ed4da46f0} + + + {1daec516-e52c-4a3c-a4da-ae3553e6e0f8} + + + + + + \ No newline at end of file diff --git a/src/Layers/xrRenderPC_GL/xrRender_GL.vcxproj.filters b/src/Layers/xrRenderPC_GL/xrRender_GL.vcxproj.filters new file mode 100644 index 00000000000..ff1cf020dee --- /dev/null +++ b/src/Layers/xrRenderPC_GL/xrRender_GL.vcxproj.filters @@ -0,0 +1,1080 @@ + + + + + {ee1c7ac7-c85c-4277-83d0-d08467b83aa7} + + + {53cb24d7-0c59-4f77-bcca-6f082e40124a} + + + {146e9dbb-6558-447e-92f5-28b6b851e62e} + + + {9cc9c9a1-1877-43a6-8427-7268cdf2e452} + + + {98f38829-c41a-4b5d-9261-eeb56b2e9c63} + + + {28ef8faa-512f-49f3-bd32-6abdcc33b954} + + + {c206756c-2f74-4863-9105-7aacea283cf7} + + + {385843e2-837b-4156-a1b1-cf2f305b90d5} + + + {2f186d78-3d83-4191-9c61-ca76bc3e9621} + + + {93ebf16f-5dcf-4b86-a40f-842f37bc4ad0} + + + {dabaf9b9-b4fd-4612-a8fe-651a62eab2dd} + + + {d4f10188-c7e9-4c6e-a6d8-dcb17fd04d2c} + + + {0ef1902c-7d1e-4870-ad88-f4e93770c6ba} + + + {eb458550-7ea0-42ac-a827-a9efee72a598} + + + {66a1a300-6848-42d9-ab20-8a9a1a1bc3fe} + + + {20490ee5-e59b-47de-85f7-3970591693e7} + + + {54677349-00b3-44ea-b629-d1e7b1f8f1b5} + + + {c95775fa-0e1f-4062-8f37-4aa12b3ed2c2} + + + {c95b8208-76b1-41f4-99c2-cb71f80a098b} + + + {551e4dd9-d957-4bb8-96d9-c37e86f15778} + + + {fccd0ac1-680a-4c70-b6ef-c8ad88018450} + + + {ce4ab461-378b-41c2-8db7-60befef3631b} + + + {389b4dc4-629d-42d1-a5a2-a951c2e5751a} + + + {993ff56e-261b-4bbc-bae1-6bd7fdf4cd12} + + + {dbe2a983-4b32-43e9-b23b-9c73c8d5e0d5} + + + {a474bbac-154c-4438-9cf3-17c51b65153f} + + + {b7d8c5f1-8720-41b7-86b8-52c2b18b6973} + + + {51f32eeb-a8a5-455d-ab60-4c08dcb67d4e} + + + {a8ac7cee-eb6c-496d-9aa2-5437e02bae08} + + + {a4f1e023-aa94-4b42-bde6-33618fe2aa71} + + + {1d86ec37-ed03-4b4a-ad08-d1136281e738} + + + {1e85b88d-02df-4201-a824-ce99fe50f29f} + + + {8c65afaf-80f3-4696-9919-73c851754961} + + + {25f1ea9c-d5c1-4075-923e-951b0fa6e6a7} + + + {24815e1d-3066-4fd1-97c0-7b32d3364fd1} + + + {fc30762e-c5ad-4274-8a8d-46e99881455e} + + + {4b7685a7-0fdc-4a10-9bdf-1f9b57f8a01e} + + + {0c371c34-8b52-45e5-8c4c-f582d12be245} + + + {1f7c26c8-fca2-4170-b9bf-367a5d89d4a5} + + + {ba78afbf-110a-482f-b44e-da7b1bd7da04} + + + {b5b51ab2-f315-499d-aec0-4054c51b45b6} + + + {219d4613-57a6-4929-9730-bf813f130ac9} + + + {ff98203c-286a-491e-b114-680b278e8c53} + + + {3b54aaa6-3ffb-4e31-b34b-eadea13eed14} + + + {c7742606-2801-4837-803f-f2761f664603} + + + {17958c5c-650a-4b55-9aee-f52d8239deb0} + + + {d37cd508-f760-4ce5-96aa-7951619d63c5} + + + {5e0e07b7-fbaa-4814-af4b-6873f02a4430} + + + {b253cb14-0c8c-4aa7-9341-c56fe542ce84} + + + {2b5eb554-65e1-43bb-9086-68c3d460b1de} + + + {2d3299ef-3c81-42e4-a4a7-864cb311777e} + + + {78baea28-4b83-4c9d-9a86-d5d29b7d1ff7} + + + {3ef93fac-90de-479d-95ab-12589c8fc6c0} + + + {8a886ec3-491c-4017-859d-ca1fe9e4a8f6} + + + {06d9c749-eea7-49a1-bd52-6a2884c2b0cf} + + + {96eff257-a076-4325-ad62-ab5e7f57e2c1} + + + {b78c2548-3b66-4839-8a06-b767341298c7} + + + {04c686d7-5f48-4735-9157-6b854b4eef34} + + + + + Kernel + + + Kernel + + + Kernel + + + Refactored\Execution & 3D\DebugDraw + + + Interface implementations\RenderFactory + + + Interface implementations\RenderDeviceRender + + + Interface implementations\Debug\DebugRender + + + Interface implementations\UI\UIRender + + + Core + + + Interface implementations\EnvironmentRender + + + Refactored\Execution & 3D\Visuals + + + Refactored\Execution & 3D\Shaders\Resources + + + Refactored\Execution & 3D\Shaders\Resources + + + Refactored\Execution & 3D\Shaders\Resources + + + Models\Visuals + + + Models\Visuals + + + Models\Visuals + + + Refactored\Backend + + + Refactored\Execution & 3D\Shaders\ShaderManager + + + Refactored\Execution & 3D\Shaders\ShaderManager + + + Refactored\Execution & 3D\Shaders\ShaderManager + + + Refactored\Execution & 3D\Shaders\ShaderManager + + + Core\memory + + + Refactored\Execution & 3D\Shaders\ShaderManager + + + Refactored\Execution & 3D\Shaders\Resources + + + Refactored\Execution & 3D\Shaders\ShaderManager + + + Refactored\Execution & 3D\Shaders\ShaderManager + + + Refactored\Execution & 3D\Shaders\Blender + + + Refactored\Execution & 3D\Shaders\Blender + + + Refactored\Execution & 3D\Shaders\Blender + + + Refactored\Execution & 3D\Shaders\Blender + + + Refactored\Execution & 3D\Shaders\Blender + + + Refactored\Execution & 3D\Shaders\Blender + + + Core + + + Refactored\Backend + + + Refactored\Backend + + + Refactored\Backend + + + Shading templates\R1 + + + Shading templates\R1 + + + Shading templates\R1 + + + Shading templates\R1 + + + Shading templates\R1 + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Refactored\Execution & 3D\Shaders\ShaderManager + + + Refactored\Execution & 3D\Shaders\ShaderManager + + + Interface implementations\UI\UIShader + + + Interface implementations\StatsRender + + + Interface implementations\ApplicationRender + + + Interface implementations\FontRender + + + Interface implementations\WallMarkArray + + + Interface implementations\ThunderboltRender + + + Interface implementations\ThunderboltDescRender + + + Interface implementations\LensFlare + + + Interface implementations\RainRender + + + Details + + + Details + + + Details + + + Details + + + Details + + + Details + + + Visibility\HOM Occlusion + + + Visibility\HOM Occlusion + + + Visibility\HOM Occlusion + + + Refactored\Backend + + + Refactored\Backend + + + Refactored\Backend + + + Refactored\Execution & 3D\Visuals + + + Refactored\Execution & 3D\Visuals + + + Refactored\Execution & 3D\Visuals + + + Core + + + Core + + + dx9 to gl Utils + + + Interface implementations\UI\UISequenceVideoItem + + + Refactored\Execution & 3D\Shaders\Resources + + + Core + + + Core + + + Core + + + Core + + + Core_Target + + + dx9 to gl Utils + + + Refactored\Execution & 3D\Shaders\Resources + + + Refactored\Execution & 3D\Shaders\Resources + + + Lights + + + Lights + + + Lights + + + Lights + + + Lights + + + Lights + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\HW + + + Visibility\Sector/Portal + + + Visibility\Sector/Portal + + + Core + + + Wallmarks + + + Lights + + + Core_Target + + + Core_Target + + + Core_Target + + + Refactored\Execution & 3D\DebugDraw + + + Refactored\Execution & 3D\DebugDraw + + + Refactored\Execution & 3D\DebugDraw + + + Refactored\Execution & 3D\DebugDraw + + + Refactored\Execution & 3D\DebugDraw + + + Models + + + Models\Visuals + + + dx9 to gl Utils + + + Models\Visuals + + + Models\Visuals + + + Models\Visuals + + + Models\Visuals + + + Interface implementations\ObjectSpaceRender + + + Core + + + Details + + + Core + + + Core_Target + + + StateManager + + + Refactored\Execution & 3D\Shaders\Resources + + + Core_Target + + + Core_Target + + + Core_Target + + + Core_Target + + + Core_Target + + + Core_Target + + + Core_Target + + + Core_Target + + + Core_Target + + + Core_Target + + + Core_Target + + + Core_Target + + + Core_Target + + + Core_Target + + + Core_Target + + + Core + + + Core + + + Lights + + + Lights + + + Core\memory + + + + + Kernel + + + Kernel + + + Refactored\Execution & 3D\DebugDraw + + + Refactored\Execution & 3D\DebugDraw + + + Interface implementations\RenderFactory + + + Interface implementations\RenderFactory + + + Interface implementations\UI\UIRender + + + Interface implementations\Debug\DebugRender + + + Interface implementations\RenderDeviceRender + + + Interface implementations\RenderDeviceRender + + + Interface implementations\Debug\DebugRender + + + Interface implementations\UI\UIRender + + + Interface implementations\EnvironmentRender + + + Core + + + Interface implementations\EnvironmentRender + + + Refactored\Execution & 3D\Visuals + + + Refactored\Execution & 3D\Visuals + + + Refactored\Execution & 3D\Visuals + + + Refactored\Execution & 3D\Shaders\Resources + + + Refactored\Execution & 3D\Shaders\Resources + + + Refactored\Execution & 3D\Shaders\Resources + + + Refactored\Execution & 3D\Shaders\Resources + + + Refactored\Execution & 3D\Shaders\Resources + + + Refactored\Execution & 3D\Shaders\Resources + + + Models\Visuals + + + Models\Visuals + + + Models\Visuals + + + Refactored\Backend + + + Refactored\Backend + + + Refactored\Backend + + + Refactored\Execution & 3D\Shaders\ShaderManager + + + Refactored\Execution & 3D\Shaders\ShaderManager + + + Refactored\Execution & 3D\Shaders\ShaderManager + + + Refactored\Execution & 3D\Shaders\Resources + + + Refactored\Execution & 3D\Shaders\Blender + + + Refactored\Execution & 3D\Shaders\Blender + + + Refactored\Execution & 3D\Shaders\Blender + + + Refactored\Execution & 3D\Shaders\Blender + + + Refactored\Execution & 3D\Shaders\Blender + + + Refactored\Backend + + + Refactored\Backend + + + Refactored\Backend + + + Refactored\Backend + + + Refactored\Backend + + + Shading templates\R1 + + + Shading templates\R1 + + + Shading templates\R1 + + + Shading templates\R1 + + + Shading templates\R1 + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Shading templates + + + Core + + + Refactored\Execution & 3D\Shaders\Resources\gl_R_shader + + + Refactored\Execution & 3D\Shaders\Resources\gl_R_shader + + + Interface implementations\UI\UIShader + + + Interface implementations\UI\UIShader + + + Interface implementations\StatsRender + + + Interface implementations\StatsRender + + + Interface implementations\ApplicationRender + + + Interface implementations\ApplicationRender + + + Interface implementations\FontRender + + + Interface implementations\FontRender + + + Interface implementations\WallMarkArray + + + Interface implementations\WallMarkArray + + + Interface implementations\ThunderboltRender + + + Interface implementations\ThunderboltDescRender + + + Interface implementations\LensFlare + + + Interface implementations\ThunderboltRender + + + Interface implementations\ThunderboltDescRender + + + Interface implementations\LensFlare + + + Interface implementations\RainRender + + + Interface implementations\RainRender + + + Details + + + Details + + + Visibility\HOM Occlusion + + + Visibility\HOM Occlusion + + + Refactored\Execution & 3D\Visuals + + + Refactored\Execution & 3D\Visuals + + + Refactored\Execution & 3D\Visuals + + + Core + + + Interface implementations\UI\UISequenceVideoItem + + + dx9 to gl Utils + + + Interface implementations\UI\UISequenceVideoItem + + + Core + + + Core + + + Core + + + Core + + + Core_Target + + + dx9 to gl Utils + + + Lights + + + Lights + + + Lights + + + Lights + + + Lights + + + Lights + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\Execution & 3D\Visuals\Skeleton + + + Refactored\HW + + + Visibility\Sector/Portal + + + Wallmarks + + + Refactored\Execution & 3D\DebugDraw + + + Refactored\Execution & 3D\DebugDraw + + + Refactored\Execution & 3D\DebugDraw + + + Refactored\Execution & 3D\DebugDraw + + + Refactored\Execution & 3D\DebugDraw + + + Models + + + Models\Visuals + + + dx9 to gl Utils + + + Models\Visuals + + + Models\Visuals + + + Models\Visuals + + + Models\Visuals + + + Interface implementations\ObjectSpaceRender + + + Interface implementations\ObjectSpaceRender + + + StateManager + + + Core_Target + + + Lights + + + Lights + + + Core\memory + + + \ No newline at end of file diff --git a/src/Layers/xrRenderPC_R1/stdafx.h b/src/Layers/xrRenderPC_R1/stdafx.h index e1ea49db5f4..755169a23e7 100644 --- a/src/Layers/xrRenderPC_R1/stdafx.h +++ b/src/Layers/xrRenderPC_R1/stdafx.h @@ -22,6 +22,7 @@ #include "Layers/xrRender/R_Backend.h" #include "Layers/xrRender/R_Backend_Runtime.h" +#define R_GL 0 #define R_R1 1 #define R_R2 2 #define R_R3 3 diff --git a/src/Layers/xrRenderPC_R2/stdafx.h b/src/Layers/xrRenderPC_R2/stdafx.h index 00064e0ea62..65dca271919 100644 --- a/src/Layers/xrRenderPC_R2/stdafx.h +++ b/src/Layers/xrRenderPC_R2/stdafx.h @@ -27,6 +27,7 @@ #include "Layers/xrRender/R_Backend.h" #include "Layers/xrRender/R_Backend_Runtime.h" +#define R_GL 0 #define R_R1 1 #define R_R2 2 #define R_R3 3 diff --git a/src/Layers/xrRenderPC_R3/stdafx.h b/src/Layers/xrRenderPC_R3/stdafx.h index 4abff5c8670..64453cdcf47 100644 --- a/src/Layers/xrRenderPC_R3/stdafx.h +++ b/src/Layers/xrRenderPC_R3/stdafx.h @@ -29,6 +29,7 @@ #include "Layers/xrRender/xrD3DDefs.h" #include "Layers/xrRender/Debug/dxPixEventWrapper.h" +#define R_GL 0 #define R_R1 1 #define R_R2 2 #define R_R3 3 diff --git a/src/Layers/xrRenderPC_R4/stdafx.h b/src/Layers/xrRenderPC_R4/stdafx.h index 8b9d3c41914..cb4263e4175 100644 --- a/src/Layers/xrRenderPC_R4/stdafx.h +++ b/src/Layers/xrRenderPC_R4/stdafx.h @@ -28,6 +28,7 @@ #include "Layers/xrRender/Debug/dxPixEventWrapper.h" +#define R_GL 0 #define R_R1 1 #define R_R2 2 #define R_R3 3 diff --git a/src/engine.sln b/src/engine.sln index bcf0d5306fc..167d64567a6 100644 --- a/src/engine.sln +++ b/src/engine.sln @@ -138,1188 +138,1724 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xrAICore", "xrAICore\xrAICo EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xrScriptEngine", "xrScriptEngine\xrScriptEngine.vcxproj", "{132C62DE-DE85-4978-9675-C78ED4DA46F0}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xrRender_GL", "Layers\xrRenderPC_GL\xrRender_GL.vcxproj", "{2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_Dedicated|Mixed Platforms = Debug_Dedicated|Mixed Platforms Debug_Dedicated|Win32 = Debug_Dedicated|Win32 + Debug_Dedicated|x64 = Debug_Dedicated|x64 Debug|Mixed Platforms = Debug|Mixed Platforms Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 Mixed_Dedicated|Mixed Platforms = Mixed_Dedicated|Mixed Platforms Mixed_Dedicated|Win32 = Mixed_Dedicated|Win32 + Mixed_Dedicated|x64 = Mixed_Dedicated|x64 Mixed|Mixed Platforms = Mixed|Mixed Platforms Mixed|Win32 = Mixed|Win32 + Mixed|x64 = Mixed|x64 Release_Dedicated|Mixed Platforms = Release_Dedicated|Mixed Platforms Release_Dedicated|Win32 = Release_Dedicated|Win32 + Release_Dedicated|x64 = Release_Dedicated|x64 Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {1BF75FEB-87DD-486C-880B-227987D191C2}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {1BF75FEB-87DD-486C-880B-227987D191C2}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {1BF75FEB-87DD-486C-880B-227987D191C2}.Debug_Dedicated|x64.Build.0 = Release|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Debug|Win32.ActiveCfg = Debug|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Debug|Win32.Build.0 = Debug|Win32 + {1BF75FEB-87DD-486C-880B-227987D191C2}.Debug|x64.ActiveCfg = Debug|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {1BF75FEB-87DD-486C-880B-227987D191C2}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {1BF75FEB-87DD-486C-880B-227987D191C2}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Mixed|Win32.ActiveCfg = Mixed|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Mixed|Win32.Build.0 = Mixed|Win32 + {1BF75FEB-87DD-486C-880B-227987D191C2}.Mixed|x64.ActiveCfg = Mixed|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {1BF75FEB-87DD-486C-880B-227987D191C2}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {1BF75FEB-87DD-486C-880B-227987D191C2}.Release_Dedicated|x64.Build.0 = Release|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Release|Mixed Platforms.Build.0 = Release|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Release|Win32.ActiveCfg = Release|Win32 {1BF75FEB-87DD-486C-880B-227987D191C2}.Release|Win32.Build.0 = Release|Win32 + {1BF75FEB-87DD-486C-880B-227987D191C2}.Release|x64.ActiveCfg = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {566551F4-4EF1-4CB4-A131-F982E7606907}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {566551F4-4EF1-4CB4-A131-F982E7606907}.Debug_Dedicated|x64.Build.0 = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Debug|Win32.ActiveCfg = Debug|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Debug|Win32.Build.0 = Debug|Win32 + {566551F4-4EF1-4CB4-A131-F982E7606907}.Debug|x64.ActiveCfg = Debug|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 + {566551F4-4EF1-4CB4-A131-F982E7606907}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {566551F4-4EF1-4CB4-A131-F982E7606907}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Mixed|Win32.ActiveCfg = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Mixed|Win32.Build.0 = Release|Win32 + {566551F4-4EF1-4CB4-A131-F982E7606907}.Mixed|x64.ActiveCfg = Release|Win32 + {566551F4-4EF1-4CB4-A131-F982E7606907}.Mixed|x64.Build.0 = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {566551F4-4EF1-4CB4-A131-F982E7606907}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {566551F4-4EF1-4CB4-A131-F982E7606907}.Release_Dedicated|x64.Build.0 = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Release|Mixed Platforms.Build.0 = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Release|Win32.ActiveCfg = Release|Win32 {566551F4-4EF1-4CB4-A131-F982E7606907}.Release|Win32.Build.0 = Release|Win32 + {566551F4-4EF1-4CB4-A131-F982E7606907}.Release|x64.ActiveCfg = Release|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Debug_Dedicated|Win32.ActiveCfg = Release|Win32 + {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Debug_Dedicated|x64.Build.0 = Release|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Debug|Win32.ActiveCfg = Debug|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Debug|Win32.Build.0 = Debug|Win32 + {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Debug|x64.ActiveCfg = Debug|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Mixed_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 + {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Mixed|Mixed Platforms.ActiveCfg = Debug|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Mixed|Mixed Platforms.Build.0 = Debug|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Mixed|Win32.ActiveCfg = Debug|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Mixed|Win32.Build.0 = Debug|Win32 + {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Mixed|x64.ActiveCfg = Release|Win32 + {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Mixed|x64.Build.0 = Release|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Release_Dedicated|x64.Build.0 = Release|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Release|Mixed Platforms.Build.0 = Release|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Release|Win32.ActiveCfg = Release|Win32 {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Release|Win32.Build.0 = Release|Win32 + {0899B131-F1D4-4876-9BA1-67AC821DB9E1}.Release|x64.ActiveCfg = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Debug_Dedicated|x64.Build.0 = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Debug|Win32.ActiveCfg = Debug|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Debug|Win32.Build.0 = Debug|Win32 + {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Debug|x64.ActiveCfg = Debug|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 + {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Mixed|Win32.ActiveCfg = Debug|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Mixed|Win32.Build.0 = Debug|Win32 + {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Mixed|x64.ActiveCfg = Release|Win32 + {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Mixed|x64.Build.0 = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Release_Dedicated|x64.Build.0 = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Release|Mixed Platforms.Build.0 = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Release|Win32.ActiveCfg = Release|Win32 {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Release|Win32.Build.0 = Release|Win32 + {C961EA19-716C-4A6D-BB13-689F8FB78B01}.Release|x64.ActiveCfg = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {2FAAC8BA-369F-465E-B465-2235963FD377}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {2FAAC8BA-369F-465E-B465-2235963FD377}.Debug_Dedicated|x64.Build.0 = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Debug|Win32.ActiveCfg = Debug|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Debug|Win32.Build.0 = Debug|Win32 + {2FAAC8BA-369F-465E-B465-2235963FD377}.Debug|x64.ActiveCfg = Debug|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 + {2FAAC8BA-369F-465E-B465-2235963FD377}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {2FAAC8BA-369F-465E-B465-2235963FD377}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Mixed|Win32.ActiveCfg = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Mixed|Win32.Build.0 = Release|Win32 + {2FAAC8BA-369F-465E-B465-2235963FD377}.Mixed|x64.ActiveCfg = Release|Win32 + {2FAAC8BA-369F-465E-B465-2235963FD377}.Mixed|x64.Build.0 = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {2FAAC8BA-369F-465E-B465-2235963FD377}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {2FAAC8BA-369F-465E-B465-2235963FD377}.Release_Dedicated|x64.Build.0 = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Release|Mixed Platforms.Build.0 = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Release|Win32.ActiveCfg = Release|Win32 {2FAAC8BA-369F-465E-B465-2235963FD377}.Release|Win32.Build.0 = Release|Win32 + {2FAAC8BA-369F-465E-B465-2235963FD377}.Release|x64.ActiveCfg = Release|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Debug_Dedicated|x64.Build.0 = Release|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Debug|Win32.ActiveCfg = Debug|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Debug|Win32.Build.0 = Debug|Win32 + {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Debug|x64.ActiveCfg = Debug|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Mixed|Win32.ActiveCfg = Mixed|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Mixed|Win32.Build.0 = Mixed|Win32 + {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Mixed|x64.ActiveCfg = Mixed|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Release_Dedicated|x64.Build.0 = Release|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Release|Mixed Platforms.Build.0 = Release|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Release|Win32.ActiveCfg = Release|Win32 {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Release|Win32.Build.0 = Release|Win32 + {65CBB9D0-FBC6-41A4-8316-F5E9B5D7FB33}.Release|x64.ActiveCfg = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Debug_Dedicated|x64.Build.0 = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Debug|Win32.ActiveCfg = Debug|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Debug|Win32.Build.0 = Debug|Win32 + {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Debug|x64.ActiveCfg = Debug|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Mixed_Dedicated|Win32.ActiveCfg = Debug|Win32 + {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Mixed|Win32.ActiveCfg = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Mixed|Win32.Build.0 = Release|Win32 + {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Mixed|x64.ActiveCfg = Release|Win32 + {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Mixed|x64.Build.0 = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Release_Dedicated|x64.Build.0 = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Release|Mixed Platforms.Build.0 = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Release|Win32.ActiveCfg = Release|Win32 {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Release|Win32.Build.0 = Release|Win32 + {A6EBBBBB-5FEF-4C20-8460-DFAB11734DED}.Release|x64.ActiveCfg = Release|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Debug_Dedicated|x64.Build.0 = Release|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Debug|Win32.ActiveCfg = Debug|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Debug|Win32.Build.0 = Debug|Win32 + {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Debug|x64.ActiveCfg = Debug|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Mixed|Win32.ActiveCfg = Mixed|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Mixed|Win32.Build.0 = Mixed|Win32 + {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Mixed|x64.ActiveCfg = Mixed|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Release_Dedicated|x64.Build.0 = Release|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Release|Mixed Platforms.Build.0 = Release|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Release|Win32.ActiveCfg = Release|Win32 {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Release|Win32.Build.0 = Release|Win32 + {EA5932F3-02FE-4AD3-89E8-7072DC465D25}.Release|x64.ActiveCfg = Release|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Debug_Dedicated|x64.Build.0 = Release|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Debug|Win32.ActiveCfg = Debug|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Debug|Win32.Build.0 = Debug|Win32 + {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Debug|x64.ActiveCfg = Debug|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Mixed|Win32.ActiveCfg = Mixed|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Mixed|Win32.Build.0 = Mixed|Win32 + {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Mixed|x64.ActiveCfg = Mixed|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Release_Dedicated|x64.Build.0 = Release|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Release|Mixed Platforms.Build.0 = Release|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Release|Win32.ActiveCfg = Release|Win32 {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Release|Win32.Build.0 = Release|Win32 + {EF76867B-6EB8-4DC0-A1D6-E964FAD6FC7B}.Release|x64.ActiveCfg = Release|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {B730F54D-1199-481A-AAD0-5DB684E067C0}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {B730F54D-1199-481A-AAD0-5DB684E067C0}.Debug_Dedicated|x64.Build.0 = Release|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Debug|Win32.ActiveCfg = Debug|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Debug|Win32.Build.0 = Debug|Win32 + {B730F54D-1199-481A-AAD0-5DB684E067C0}.Debug|x64.ActiveCfg = Debug|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {B730F54D-1199-481A-AAD0-5DB684E067C0}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {B730F54D-1199-481A-AAD0-5DB684E067C0}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Mixed|Win32.ActiveCfg = Mixed|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Mixed|Win32.Build.0 = Mixed|Win32 + {B730F54D-1199-481A-AAD0-5DB684E067C0}.Mixed|x64.ActiveCfg = Mixed|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {B730F54D-1199-481A-AAD0-5DB684E067C0}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {B730F54D-1199-481A-AAD0-5DB684E067C0}.Release_Dedicated|x64.Build.0 = Release|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Release|Mixed Platforms.Build.0 = Release|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Release|Win32.ActiveCfg = Release|Win32 {B730F54D-1199-481A-AAD0-5DB684E067C0}.Release|Win32.Build.0 = Release|Win32 + {B730F54D-1199-481A-AAD0-5DB684E067C0}.Release|x64.ActiveCfg = Release|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Debug_Dedicated|x64.Build.0 = Release|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Debug|Win32.ActiveCfg = Debug|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Debug|Win32.Build.0 = Debug|Win32 + {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Debug|x64.ActiveCfg = Debug|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Mixed|Win32.ActiveCfg = Mixed|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Mixed|Win32.Build.0 = Mixed|Win32 + {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Mixed|x64.ActiveCfg = Mixed|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Release_Dedicated|x64.Build.0 = Release|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Release|Mixed Platforms.Build.0 = Release|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Release|Win32.ActiveCfg = Release|Win32 {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Release|Win32.Build.0 = Release|Win32 + {EBF9B543-0830-4866-9B48-DC0740E87E8A}.Release|x64.ActiveCfg = Release|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Debug_Dedicated|x64.Build.0 = Release|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Debug|Win32.ActiveCfg = Debug|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Debug|Win32.Build.0 = Debug|Win32 + {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Debug|x64.ActiveCfg = Debug|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Mixed|Win32.ActiveCfg = Mixed|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Mixed|Win32.Build.0 = Mixed|Win32 + {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Mixed|x64.ActiveCfg = Mixed|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Release_Dedicated|x64.Build.0 = Release|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Release|Mixed Platforms.Build.0 = Release|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Release|Win32.ActiveCfg = Release|Win32 {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Release|Win32.Build.0 = Release|Win32 + {A4ABD75E-825B-4D09-B3B2-2709682E40C8}.Release|x64.ActiveCfg = Release|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Debug_Dedicated|x64.Build.0 = Release|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Debug|Win32.ActiveCfg = Debug|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Debug|Win32.Build.0 = Debug|Win32 + {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Debug|x64.ActiveCfg = Debug|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Mixed|Win32.ActiveCfg = Mixed|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Mixed|Win32.Build.0 = Mixed|Win32 + {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Mixed|x64.ActiveCfg = Mixed|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Release_Dedicated|x64.Build.0 = Release|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Release|Mixed Platforms.Build.0 = Release|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Release|Win32.ActiveCfg = Release|Win32 {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Release|Win32.Build.0 = Release|Win32 + {F1836CE2-59EF-4189-8B9C-D103A511CB27}.Release|x64.ActiveCfg = Release|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Debug_Dedicated|x64.Build.0 = Release|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Debug|Win32.ActiveCfg = Debug|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Debug|Win32.Build.0 = Debug|Win32 + {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Debug|x64.ActiveCfg = Debug|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Mixed|Win32.ActiveCfg = Mixed|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Mixed|Win32.Build.0 = Mixed|Win32 + {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Mixed|x64.ActiveCfg = Mixed|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Release_Dedicated|x64.Build.0 = Release|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Release|Mixed Platforms.Build.0 = Release|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Release|Win32.ActiveCfg = Release|Win32 {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Release|Win32.Build.0 = Release|Win32 + {3AD26FD3-4F52-4E22-A4CF-AD4C49E74C61}.Release|x64.ActiveCfg = Release|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Debug_Dedicated|x64.Build.0 = Release|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Debug|Win32.ActiveCfg = Debug|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Debug|Win32.Build.0 = Debug|Win32 + {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Debug|x64.ActiveCfg = Debug|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Mixed|Win32.ActiveCfg = Mixed|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Mixed|Win32.Build.0 = Mixed|Win32 + {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Mixed|x64.ActiveCfg = Mixed|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Release_Dedicated|x64.Build.0 = Release|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Release|Mixed Platforms.Build.0 = Release|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Release|Win32.ActiveCfg = Release|Win32 {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Release|Win32.Build.0 = Release|Win32 + {A19B1DF2-82EC-4364-8BDF-85D13A1C89B5}.Release|x64.ActiveCfg = Release|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Debug_Dedicated|x64.Build.0 = Release|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Debug|Win32.ActiveCfg = Debug|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Debug|Win32.Build.0 = Debug|Win32 + {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Debug|x64.ActiveCfg = Debug|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Mixed|Win32.ActiveCfg = Mixed|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Mixed|Win32.Build.0 = Mixed|Win32 + {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Mixed|x64.ActiveCfg = Mixed|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Release_Dedicated|x64.Build.0 = Release|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Release|Mixed Platforms.Build.0 = Release|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Release|Win32.ActiveCfg = Release|Win32 {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Release|Win32.Build.0 = Release|Win32 + {A0F7D1FB-59A7-4717-A7E4-96F37E91998E}.Release|x64.ActiveCfg = Release|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {200652A6-043E-4634-8837-87983B3BD5E0}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {200652A6-043E-4634-8837-87983B3BD5E0}.Debug_Dedicated|x64.Build.0 = Release|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Debug|Win32.ActiveCfg = Debug|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Debug|Win32.Build.0 = Debug|Win32 + {200652A6-043E-4634-8837-87983B3BD5E0}.Debug|x64.ActiveCfg = Debug|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Mixed_Dedicated|Win32.ActiveCfg = Debug|Win32 + {200652A6-043E-4634-8837-87983B3BD5E0}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {200652A6-043E-4634-8837-87983B3BD5E0}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Mixed|Win32.ActiveCfg = Debug|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Mixed|Win32.Build.0 = Debug|Win32 + {200652A6-043E-4634-8837-87983B3BD5E0}.Mixed|x64.ActiveCfg = Mixed|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {200652A6-043E-4634-8837-87983B3BD5E0}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {200652A6-043E-4634-8837-87983B3BD5E0}.Release_Dedicated|x64.Build.0 = Release|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Release|Mixed Platforms.Build.0 = Release|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Release|Win32.ActiveCfg = Release|Win32 {200652A6-043E-4634-8837-87983B3BD5E0}.Release|Win32.Build.0 = Release|Win32 + {200652A6-043E-4634-8837-87983B3BD5E0}.Release|x64.ActiveCfg = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Debug_Dedicated|x64.Build.0 = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Debug|Win32.ActiveCfg = Debug|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Debug|Win32.Build.0 = Debug|Win32 + {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Debug|x64.ActiveCfg = Debug|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 + {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Mixed|Win32.ActiveCfg = Debug|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Mixed|Win32.Build.0 = Debug|Win32 + {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Mixed|x64.ActiveCfg = Release|Win32 + {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Mixed|x64.Build.0 = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Release_Dedicated|x64.Build.0 = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Release|Mixed Platforms.Build.0 = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Release|Win32.ActiveCfg = Release|Win32 {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Release|Win32.Build.0 = Release|Win32 + {5535F6B4-7AE6-4B66-8AEA-CC31C14D7AB7}.Release|x64.ActiveCfg = Release|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Debug_Dedicated|x64.Build.0 = Release|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Debug|Win32.ActiveCfg = Debug|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Debug|Win32.Build.0 = Debug|Win32 + {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Debug|x64.ActiveCfg = Debug|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Mixed|Win32.ActiveCfg = Debug|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Mixed|Win32.Build.0 = Debug|Win32 + {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Mixed|x64.ActiveCfg = Mixed|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Release_Dedicated|x64.Build.0 = Release|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Release|Mixed Platforms.Build.0 = Release|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Release|Win32.ActiveCfg = Release|Win32 {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Release|Win32.Build.0 = Release|Win32 + {435BAC9A-B225-457D-AB40-C9BD0CC8838C}.Release|x64.ActiveCfg = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Debug_Dedicated|x64.Build.0 = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Debug|Win32.ActiveCfg = Debug|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Debug|Win32.Build.0 = Debug|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Debug|x64.ActiveCfg = Debug|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Mixed|Win32.ActiveCfg = Mixed|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Mixed|Win32.Build.0 = Mixed|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Mixed|x64.ActiveCfg = Mixed|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Release_Dedicated|x64.Build.0 = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Release|Mixed Platforms.Build.0 = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Release|Win32.ActiveCfg = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Release|Win32.Build.0 = Release|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF97}.Release|x64.ActiveCfg = Release|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Debug_Dedicated|x64.Build.0 = Release|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Debug|Win32.ActiveCfg = Debug|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Debug|Win32.Build.0 = Debug|Win32 + {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Debug|x64.ActiveCfg = Debug|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Mixed|Win32.ActiveCfg = Debug|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Mixed|Win32.Build.0 = Debug|Win32 + {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Mixed|x64.ActiveCfg = Mixed|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Release_Dedicated|x64.Build.0 = Release|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Release|Mixed Platforms.Build.0 = Release|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Release|Win32.ActiveCfg = Release|Win32 {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Release|Win32.Build.0 = Release|Win32 + {57A498C9-A741-4DDF-8EFC-BFB9EB6B00E2}.Release|x64.ActiveCfg = Release|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Debug_Dedicated|x64.Build.0 = Release|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Debug|Win32.ActiveCfg = Debug|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Debug|Win32.Build.0 = Debug|Win32 + {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Debug|x64.ActiveCfg = Debug|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Mixed|Win32.ActiveCfg = Debug|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Mixed|Win32.Build.0 = Debug|Win32 + {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Mixed|x64.ActiveCfg = Mixed|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Release_Dedicated|x64.Build.0 = Release|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Release|Mixed Platforms.Build.0 = Release|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Release|Win32.ActiveCfg = Release|Win32 {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Release|Win32.Build.0 = Release|Win32 + {963BA4E5-499A-454D-B002-1D5ECE0527A6}.Release|x64.ActiveCfg = Release|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Debug_Dedicated|x64.Build.0 = Release|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Debug|Win32.ActiveCfg = Debug|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Debug|Win32.Build.0 = Debug|Win32 + {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Debug|x64.ActiveCfg = Debug|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Mixed|Win32.ActiveCfg = Mixed|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Mixed|Win32.Build.0 = Mixed|Win32 + {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Mixed|x64.ActiveCfg = Mixed|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Release_Dedicated|x64.Build.0 = Release|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Release|Mixed Platforms.Build.0 = Release|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Release|Win32.ActiveCfg = Release|Win32 {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Release|Win32.Build.0 = Release|Win32 + {CCCA7859-EB86-493E-9B53-C4235F45B3C5}.Release|x64.ActiveCfg = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Debug_Dedicated|x64.Build.0 = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Debug|Win32.ActiveCfg = Debug|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Debug|Win32.Build.0 = Debug|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Debug|x64.ActiveCfg = Debug|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Mixed|Win32.ActiveCfg = Mixed|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Mixed|Win32.Build.0 = Mixed|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Mixed|x64.ActiveCfg = Mixed|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Release_Dedicated|x64.Build.0 = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Release|Mixed Platforms.Build.0 = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Release|Win32.ActiveCfg = Release|Win32 {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Release|Win32.Build.0 = Release|Win32 + {94A1C366-3D19-48E6-8170-4ADC2E70DF98}.Release|x64.ActiveCfg = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {F573DE85-0866-4775-955F-6C3241D2AE80}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {F573DE85-0866-4775-955F-6C3241D2AE80}.Debug_Dedicated|x64.Build.0 = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Debug|Win32.ActiveCfg = Debug|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Debug|Win32.Build.0 = Debug|Win32 + {F573DE85-0866-4775-955F-6C3241D2AE80}.Debug|x64.ActiveCfg = Debug|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Mixed_Dedicated|Win32.ActiveCfg = Debug|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Mixed_Dedicated|Win32.Build.0 = Debug|Win32 + {F573DE85-0866-4775-955F-6C3241D2AE80}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {F573DE85-0866-4775-955F-6C3241D2AE80}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Mixed|Win32.ActiveCfg = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Mixed|Win32.Build.0 = Release|Win32 + {F573DE85-0866-4775-955F-6C3241D2AE80}.Mixed|x64.ActiveCfg = Release|Win32 + {F573DE85-0866-4775-955F-6C3241D2AE80}.Mixed|x64.Build.0 = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {F573DE85-0866-4775-955F-6C3241D2AE80}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {F573DE85-0866-4775-955F-6C3241D2AE80}.Release_Dedicated|x64.Build.0 = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Release|Mixed Platforms.Build.0 = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Release|Win32.ActiveCfg = Release|Win32 {F573DE85-0866-4775-955F-6C3241D2AE80}.Release|Win32.Build.0 = Release|Win32 + {F573DE85-0866-4775-955F-6C3241D2AE80}.Release|x64.ActiveCfg = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Debug_Dedicated|x64.Build.0 = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Debug|Win32.ActiveCfg = Debug|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Debug|Win32.Build.0 = Debug|Win32 + {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Debug|x64.ActiveCfg = Debug|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Mixed_Dedicated|Win32.ActiveCfg = Debug|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Mixed_Dedicated|Win32.Build.0 = Debug|Win32 + {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Mixed|Win32.ActiveCfg = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Mixed|Win32.Build.0 = Release|Win32 + {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Mixed|x64.ActiveCfg = Release|Win32 + {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Mixed|x64.Build.0 = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Release_Dedicated|x64.Build.0 = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Release|Mixed Platforms.Build.0 = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Release|Win32.ActiveCfg = Release|Win32 {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Release|Win32.Build.0 = Release|Win32 + {6BA3121A-ACBC-4685-9246-4549CA1EFFFD}.Release|x64.ActiveCfg = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Debug_Dedicated|x64.Build.0 = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Debug|Win32.ActiveCfg = Debug|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Debug|Win32.Build.0 = Debug|Win32 + {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Debug|x64.ActiveCfg = Debug|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Mixed_Dedicated|Win32.ActiveCfg = Debug|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Mixed_Dedicated|Win32.Build.0 = Debug|Win32 + {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Mixed|Win32.ActiveCfg = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Mixed|Win32.Build.0 = Release|Win32 + {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Mixed|x64.ActiveCfg = Release|Win32 + {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Mixed|x64.Build.0 = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Release_Dedicated|x64.Build.0 = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Release|Mixed Platforms.Build.0 = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Release|Win32.ActiveCfg = Release|Win32 {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Release|Win32.Build.0 = Release|Win32 + {39EE310B-4F1D-4716-A39F-4AB844DB3680}.Release|x64.ActiveCfg = Release|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Debug_Dedicated|x64.Build.0 = Release|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Debug|Win32.ActiveCfg = Debug|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Debug|Win32.Build.0 = Debug|Win32 + {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Debug|x64.ActiveCfg = Debug|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Mixed_Dedicated|Win32.Build.0 = Mixed|Win32 + {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Mixed|Win32.ActiveCfg = Release|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Mixed|Win32.Build.0 = Release|Win32 + {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Mixed|x64.ActiveCfg = Mixed|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Release_Dedicated|x64.Build.0 = Release|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Release|Mixed Platforms.Build.0 = Release|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Release|Win32.ActiveCfg = Release|Win32 {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Release|Win32.Build.0 = Release|Win32 + {93AD3B7E-71DE-4FA2-90E7-A79782ED4960}.Release|x64.ActiveCfg = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Debug_Dedicated|x64.Build.0 = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Debug|Win32.ActiveCfg = Debug|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Debug|Win32.Build.0 = Debug|Win32 + {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Debug|x64.ActiveCfg = Debug|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 + {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Mixed|Win32.ActiveCfg = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Mixed|Win32.Build.0 = Release|Win32 + {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Mixed|x64.ActiveCfg = Release|Win32 + {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Mixed|x64.Build.0 = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Release_Dedicated|x64.Build.0 = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Release|Mixed Platforms.Build.0 = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Release|Win32.ActiveCfg = Release|Win32 {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Release|Win32.Build.0 = Release|Win32 + {56AD8F54-F89E-4B5A-93F8-8A617BFD1160}.Release|x64.ActiveCfg = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Debug_Dedicated|x64.Build.0 = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Debug|Win32.ActiveCfg = Debug|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Debug|Win32.Build.0 = Debug|Win32 + {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Debug|x64.ActiveCfg = Debug|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Mixed_Dedicated|Win32.Build.0 = Release|Win32 + {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Mixed|Win32.ActiveCfg = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Mixed|Win32.Build.0 = Release|Win32 + {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Mixed|x64.ActiveCfg = Release|Win32 + {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Mixed|x64.Build.0 = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Release_Dedicated|x64.Build.0 = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Release|Mixed Platforms.Build.0 = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Release|Win32.ActiveCfg = Release|Win32 {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Release|Win32.Build.0 = Release|Win32 + {C928FBB1-EDD8-4198-90DC-170A54C2AD72}.Release|x64.ActiveCfg = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Debug_Dedicated|x64.Build.0 = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Debug|Win32.ActiveCfg = Debug|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Debug|Win32.Build.0 = Debug|Win32 + {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Debug|x64.ActiveCfg = Debug|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Mixed_Dedicated|Win32.Build.0 = Release|Win32 + {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Mixed|Win32.ActiveCfg = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Mixed|Win32.Build.0 = Release|Win32 + {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Mixed|x64.ActiveCfg = Release|Win32 + {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Mixed|x64.Build.0 = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Release_Dedicated|x64.Build.0 = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Release|Mixed Platforms.Build.0 = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Release|Win32.ActiveCfg = Release|Win32 {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Release|Win32.Build.0 = Release|Win32 + {84D91673-C1A1-47FF-9A75-4E73F31F4C63}.Release|x64.ActiveCfg = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Debug_Dedicated|x64.Build.0 = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Debug|Win32.ActiveCfg = Debug|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Debug|Win32.Build.0 = Debug|Win32 + {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Debug|x64.ActiveCfg = Debug|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Mixed_Dedicated|Win32.ActiveCfg = Debug|Win32 + {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Mixed|Win32.ActiveCfg = Debug|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Mixed|Win32.Build.0 = Debug|Win32 + {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Mixed|x64.ActiveCfg = Release|Win32 + {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Mixed|x64.Build.0 = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Release_Dedicated|x64.Build.0 = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Release|Mixed Platforms.Build.0 = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Release|Win32.ActiveCfg = Release|Win32 {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Release|Win32.Build.0 = Release|Win32 + {1DAEC516-E52C-4A3C-A4DA-AE3553E6E0F8}.Release|x64.ActiveCfg = Release|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {3F383D3C-FCD8-4170-990B-EB4833F09248}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {3F383D3C-FCD8-4170-990B-EB4833F09248}.Debug_Dedicated|x64.Build.0 = Release|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Debug|Win32.ActiveCfg = Debug|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Debug|Win32.Build.0 = Debug|Win32 + {3F383D3C-FCD8-4170-990B-EB4833F09248}.Debug|x64.ActiveCfg = Debug|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {3F383D3C-FCD8-4170-990B-EB4833F09248}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {3F383D3C-FCD8-4170-990B-EB4833F09248}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Mixed|Win32.ActiveCfg = Debug|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Mixed|Win32.Build.0 = Debug|Win32 + {3F383D3C-FCD8-4170-990B-EB4833F09248}.Mixed|x64.ActiveCfg = Mixed|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {3F383D3C-FCD8-4170-990B-EB4833F09248}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {3F383D3C-FCD8-4170-990B-EB4833F09248}.Release_Dedicated|x64.Build.0 = Release|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Release|Mixed Platforms.Build.0 = Release|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Release|Win32.ActiveCfg = Release|Win32 {3F383D3C-FCD8-4170-990B-EB4833F09248}.Release|Win32.Build.0 = Release|Win32 + {3F383D3C-FCD8-4170-990B-EB4833F09248}.Release|x64.ActiveCfg = Release|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug_Dedicated|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug_Dedicated|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Debug_Dedicated|Win32.ActiveCfg = Debug_Dedicated|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Debug_Dedicated|Win32.Build.0 = Debug_Dedicated|Win32 + {2578C6D8-660D-48AE-9322-7422F8664F06}.Debug_Dedicated|x64.ActiveCfg = Debug_Dedicated|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Debug|Win32.ActiveCfg = Debug|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Debug|Win32.Build.0 = Debug|Win32 + {2578C6D8-660D-48AE-9322-7422F8664F06}.Debug|x64.ActiveCfg = Debug|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed_Dedicated|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed_Dedicated|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Mixed_Dedicated|Win32.ActiveCfg = Mixed_Dedicated|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Mixed_Dedicated|Win32.Build.0 = Mixed_Dedicated|Win32 + {2578C6D8-660D-48AE-9322-7422F8664F06}.Mixed_Dedicated|x64.ActiveCfg = Mixed_Dedicated|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Mixed|Win32.ActiveCfg = Debug|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Mixed|Win32.Build.0 = Debug|Win32 + {2578C6D8-660D-48AE-9322-7422F8664F06}.Mixed|x64.ActiveCfg = Mixed|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release_Dedicated|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Release_Dedicated|Mixed Platforms.Build.0 = Release_Dedicated|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Release_Dedicated|Win32.ActiveCfg = Release_Dedicated|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Release_Dedicated|Win32.Build.0 = Release_Dedicated|Win32 + {2578C6D8-660D-48AE-9322-7422F8664F06}.Release_Dedicated|x64.ActiveCfg = Release_Dedicated|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Release|Mixed Platforms.Build.0 = Release|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Release|Win32.ActiveCfg = Release|Win32 {2578C6D8-660D-48AE-9322-7422F8664F06}.Release|Win32.Build.0 = Release|Win32 + {2578C6D8-660D-48AE-9322-7422F8664F06}.Release|x64.ActiveCfg = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Debug_Dedicated|x64.Build.0 = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Debug|Win32.ActiveCfg = Debug|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Debug|Win32.Build.0 = Debug|Win32 + {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Debug|x64.ActiveCfg = Debug|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Mixed_Dedicated|Win32.ActiveCfg = Debug|Win32 + {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Mixed|Win32.ActiveCfg = Debug|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Mixed|Win32.Build.0 = Debug|Win32 + {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Mixed|x64.ActiveCfg = Release|Win32 + {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Mixed|x64.Build.0 = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Release_Dedicated|x64.Build.0 = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Release|Mixed Platforms.Build.0 = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Release|Win32.ActiveCfg = Release|Win32 {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Release|Win32.Build.0 = Release|Win32 + {CC52E0B3-CC35-4934-9302-035B748F3F2C}.Release|x64.ActiveCfg = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {F6C4F74A-152C-4612-9E3B-D02346234855}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {F6C4F74A-152C-4612-9E3B-D02346234855}.Debug_Dedicated|x64.Build.0 = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Debug|Win32.ActiveCfg = Debug|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Debug|Win32.Build.0 = Debug|Win32 + {F6C4F74A-152C-4612-9E3B-D02346234855}.Debug|x64.ActiveCfg = Debug|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Mixed_Dedicated|Win32.ActiveCfg = Debug|Win32 + {F6C4F74A-152C-4612-9E3B-D02346234855}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {F6C4F74A-152C-4612-9E3B-D02346234855}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Mixed|Win32.ActiveCfg = Debug|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Mixed|Win32.Build.0 = Debug|Win32 + {F6C4F74A-152C-4612-9E3B-D02346234855}.Mixed|x64.ActiveCfg = Release|Win32 + {F6C4F74A-152C-4612-9E3B-D02346234855}.Mixed|x64.Build.0 = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {F6C4F74A-152C-4612-9E3B-D02346234855}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {F6C4F74A-152C-4612-9E3B-D02346234855}.Release_Dedicated|x64.Build.0 = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Release|Mixed Platforms.Build.0 = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Release|Win32.ActiveCfg = Release|Win32 {F6C4F74A-152C-4612-9E3B-D02346234855}.Release|Win32.Build.0 = Release|Win32 + {F6C4F74A-152C-4612-9E3B-D02346234855}.Release|x64.ActiveCfg = Release|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Debug_Dedicated|x64.Build.0 = Release|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Debug|Win32.ActiveCfg = Debug|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Debug|Win32.Build.0 = Debug|Win32 + {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Debug|x64.ActiveCfg = Debug|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 + {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Mixed|Win32.ActiveCfg = Mixed|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Mixed|Win32.Build.0 = Mixed|Win32 + {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Mixed|x64.ActiveCfg = Mixed|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Release_Dedicated|x64.Build.0 = Release|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Release|Mixed Platforms.Build.0 = Release|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Release|Win32.ActiveCfg = Release|Win32 {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Release|Win32.Build.0 = Release|Win32 + {EFB76D6F-0092-439C-A783-C0BE10BD17C9}.Release|x64.ActiveCfg = Release|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Debug_Dedicated|x64.Build.0 = Release|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Debug|Win32.ActiveCfg = Debug|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Debug|Win32.Build.0 = Debug|Win32 + {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Debug|x64.ActiveCfg = Debug|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Mixed|Win32.ActiveCfg = Mixed|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Mixed|Win32.Build.0 = Mixed|Win32 + {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Mixed|x64.ActiveCfg = Mixed|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Release_Dedicated|x64.Build.0 = Release|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Release|Mixed Platforms.Build.0 = Release|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Release|Win32.ActiveCfg = Release|Win32 {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Release|Win32.Build.0 = Release|Win32 + {EC924B9B-4991-4931-8623-E1DB9AE005CA}.Release|x64.ActiveCfg = Release|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Debug_Dedicated|x64.Build.0 = Release|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Debug|Win32.ActiveCfg = Debug|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Debug|Win32.Build.0 = Debug|Win32 + {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Debug|x64.ActiveCfg = Debug|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Mixed|Win32.ActiveCfg = Mixed|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Mixed|Win32.Build.0 = Mixed|Win32 + {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Mixed|x64.ActiveCfg = Mixed|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Release_Dedicated|x64.Build.0 = Release|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Release|Mixed Platforms.Build.0 = Release|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Release|Win32.ActiveCfg = Release|Win32 {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Release|Win32.Build.0 = Release|Win32 + {98D24A3D-7666-4C11-9D6E-B10393CE8CBA}.Release|x64.ActiveCfg = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Debug_Dedicated|x64.Build.0 = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Debug|Win32.ActiveCfg = Debug|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Debug|Win32.Build.0 = Debug|Win32 + {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Debug|x64.ActiveCfg = Debug|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Mixed_Dedicated|Win32.Build.0 = Release|Win32 + {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Mixed|Win32.ActiveCfg = Debug|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Mixed|Win32.Build.0 = Debug|Win32 + {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Mixed|x64.ActiveCfg = Release|Win32 + {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Mixed|x64.Build.0 = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Release_Dedicated|x64.Build.0 = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Release|Mixed Platforms.Build.0 = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Release|Win32.ActiveCfg = Release|Win32 {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Release|Win32.Build.0 = Release|Win32 + {E5F40F9E-C01B-4B97-9BD5-FC24308D8022}.Release|x64.ActiveCfg = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Debug_Dedicated|x64.Build.0 = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Debug|Win32.ActiveCfg = Debug|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Debug|Win32.Build.0 = Debug|Win32 + {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Debug|x64.ActiveCfg = Debug|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Mixed_Dedicated|Win32.Build.0 = Release|Win32 + {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Mixed|Win32.ActiveCfg = Debug|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Mixed|Win32.Build.0 = Debug|Win32 + {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Mixed|x64.ActiveCfg = Release|Win32 + {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Mixed|x64.Build.0 = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Release_Dedicated|x64.Build.0 = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Release|Mixed Platforms.Build.0 = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Release|Win32.ActiveCfg = Release|Win32 {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Release|Win32.Build.0 = Release|Win32 + {FFDF27A8-C198-49ED-BA13-4DA9054266C6}.Release|x64.ActiveCfg = Release|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Debug_Dedicated|x64.Build.0 = Release|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Debug|Win32.ActiveCfg = Debug|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Debug|Win32.Build.0 = Debug|Win32 + {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Debug|x64.ActiveCfg = Debug|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Mixed|Win32.ActiveCfg = Debug|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Mixed|Win32.Build.0 = Debug|Win32 + {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Mixed|x64.ActiveCfg = Mixed|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Release_Dedicated|x64.Build.0 = Release|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Release|Mixed Platforms.Build.0 = Release|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Release|Win32.ActiveCfg = Release|Win32 {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Release|Win32.Build.0 = Release|Win32 + {AC9B12ED-A2D7-4337-A981-5BD8430E96D8}.Release|x64.ActiveCfg = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {032A10AB-E44C-4751-A290-001EF99E664A}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {032A10AB-E44C-4751-A290-001EF99E664A}.Debug_Dedicated|x64.Build.0 = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Debug|Win32.ActiveCfg = Debug|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Debug|Win32.Build.0 = Debug|Win32 + {032A10AB-E44C-4751-A290-001EF99E664A}.Debug|x64.ActiveCfg = Debug|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Mixed_Dedicated|Win32.ActiveCfg = Debug|Win32 + {032A10AB-E44C-4751-A290-001EF99E664A}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {032A10AB-E44C-4751-A290-001EF99E664A}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Mixed|Win32.ActiveCfg = Debug|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Mixed|Win32.Build.0 = Debug|Win32 + {032A10AB-E44C-4751-A290-001EF99E664A}.Mixed|x64.ActiveCfg = Release|Win32 + {032A10AB-E44C-4751-A290-001EF99E664A}.Mixed|x64.Build.0 = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {032A10AB-E44C-4751-A290-001EF99E664A}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {032A10AB-E44C-4751-A290-001EF99E664A}.Release_Dedicated|x64.Build.0 = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Release|Mixed Platforms.Build.0 = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Release|Win32.ActiveCfg = Release|Win32 {032A10AB-E44C-4751-A290-001EF99E664A}.Release|Win32.Build.0 = Release|Win32 + {032A10AB-E44C-4751-A290-001EF99E664A}.Release|x64.ActiveCfg = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Debug_Dedicated|x64.Build.0 = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Debug|Win32.ActiveCfg = Debug|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Debug|Win32.Build.0 = Debug|Win32 + {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Debug|x64.ActiveCfg = Debug|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Mixed_Dedicated|Win32.ActiveCfg = Debug|Win32 + {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Mixed|Win32.ActiveCfg = Debug|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Mixed|Win32.Build.0 = Debug|Win32 + {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Mixed|x64.ActiveCfg = Release|Win32 + {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Mixed|x64.Build.0 = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Release_Dedicated|x64.Build.0 = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Release|Mixed Platforms.Build.0 = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Release|Win32.ActiveCfg = Release|Win32 {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Release|Win32.Build.0 = Release|Win32 + {1924EF23-A05E-40E5-93F2-6CCD64BE1F8B}.Release|x64.ActiveCfg = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Debug_Dedicated|x64.Build.0 = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Debug|Win32.ActiveCfg = Debug|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Debug|Win32.Build.0 = Debug|Win32 + {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Debug|x64.ActiveCfg = Debug|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Mixed_Dedicated|Win32.Build.0 = Release|Win32 + {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Mixed|Win32.ActiveCfg = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Mixed|Win32.Build.0 = Release|Win32 + {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Mixed|x64.ActiveCfg = Release|Win32 + {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Mixed|x64.Build.0 = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Release_Dedicated|x64.Build.0 = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Release|Mixed Platforms.Build.0 = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Release|Win32.ActiveCfg = Release|Win32 {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Release|Win32.Build.0 = Release|Win32 + {880CD250-BA77-4DAF-A8D4-552F12DD3AE4}.Release|x64.ActiveCfg = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Debug_Dedicated|x64.Build.0 = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Debug|Win32.ActiveCfg = Debug|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Debug|Win32.Build.0 = Debug|Win32 + {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Debug|x64.ActiveCfg = Debug|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Mixed_Dedicated|Win32.Build.0 = Release|Win32 + {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Mixed|Win32.ActiveCfg = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Mixed|Win32.Build.0 = Release|Win32 + {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Mixed|x64.ActiveCfg = Release|Win32 + {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Mixed|x64.Build.0 = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Release_Dedicated|x64.Build.0 = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Release|Mixed Platforms.Build.0 = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Release|Win32.ActiveCfg = Release|Win32 {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Release|Win32.Build.0 = Release|Win32 + {0EB257DC-5CFC-44B0-82C9-CE6B158BE473}.Release|x64.ActiveCfg = Release|Win32 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Debug_Dedicated|Win32.ActiveCfg = Debug|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Debug_Dedicated|Win32.Build.0 = Debug|x86 + {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Debug_Dedicated|x64.ActiveCfg = Release|x86 + {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Debug_Dedicated|x64.Build.0 = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Debug|Mixed Platforms.Build.0 = Debug|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Debug|Win32.ActiveCfg = Debug|x86 - {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Debug|Win32.Build.0 = Debug|x86 + {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Debug|x64.ActiveCfg = Debug|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Mixed_Dedicated|Win32.ActiveCfg = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Mixed_Dedicated|Win32.Build.0 = Release|x86 + {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Mixed_Dedicated|x64.ActiveCfg = Release|x86 + {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Mixed_Dedicated|x64.Build.0 = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Mixed|Mixed Platforms.ActiveCfg = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Mixed|Mixed Platforms.Build.0 = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Mixed|Win32.ActiveCfg = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Mixed|Win32.Build.0 = Release|x86 + {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Mixed|x64.ActiveCfg = Release|x86 + {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Mixed|x64.Build.0 = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Release_Dedicated|Mixed Platforms.Build.0 = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Release_Dedicated|Win32.ActiveCfg = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Release_Dedicated|Win32.Build.0 = Release|x86 + {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Release_Dedicated|x64.ActiveCfg = Release|x86 + {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Release_Dedicated|x64.Build.0 = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Release|Mixed Platforms.ActiveCfg = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Release|Mixed Platforms.Build.0 = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Release|Win32.ActiveCfg = Release|x86 {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Release|Win32.Build.0 = Release|x86 + {E9DC16A3-D0FA-4924-AF6E-F6FDF3EA0661}.Release|x64.ActiveCfg = Release|x86 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Debug_Dedicated|x64.Build.0 = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Debug|Win32.ActiveCfg = Debug|Win32 - {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Debug|Win32.Build.0 = Debug|Win32 + {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Debug|x64.ActiveCfg = Debug|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Mixed_Dedicated|Win32.Build.0 = Release|Win32 + {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Mixed|Win32.ActiveCfg = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Mixed|Win32.Build.0 = Release|Win32 + {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Mixed|x64.ActiveCfg = Release|Win32 + {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Mixed|x64.Build.0 = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Release_Dedicated|x64.Build.0 = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Release|Mixed Platforms.Build.0 = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Release|Win32.ActiveCfg = Release|Win32 {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Release|Win32.Build.0 = Release|Win32 + {492D3DFE-9068-4E7E-A008-7C2420A651C0}.Release|x64.ActiveCfg = Release|Win32 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Debug_Dedicated|Win32.ActiveCfg = Debug|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Debug_Dedicated|Win32.Build.0 = Debug|x86 + {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Debug_Dedicated|x64.ActiveCfg = Release|x86 + {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Debug_Dedicated|x64.Build.0 = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Debug|Mixed Platforms.Build.0 = Debug|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Debug|Win32.ActiveCfg = Debug|x86 - {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Debug|Win32.Build.0 = Debug|x86 + {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Debug|x64.ActiveCfg = Debug|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Mixed_Dedicated|Win32.ActiveCfg = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Mixed_Dedicated|Win32.Build.0 = Release|x86 + {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Mixed_Dedicated|x64.ActiveCfg = Release|x86 + {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Mixed_Dedicated|x64.Build.0 = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Mixed|Mixed Platforms.ActiveCfg = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Mixed|Mixed Platforms.Build.0 = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Mixed|Win32.ActiveCfg = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Mixed|Win32.Build.0 = Release|x86 + {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Mixed|x64.ActiveCfg = Release|x86 + {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Mixed|x64.Build.0 = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Release_Dedicated|Mixed Platforms.Build.0 = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Release_Dedicated|Win32.ActiveCfg = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Release_Dedicated|Win32.Build.0 = Release|x86 + {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Release_Dedicated|x64.ActiveCfg = Release|x86 + {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Release_Dedicated|x64.Build.0 = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Release|Mixed Platforms.ActiveCfg = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Release|Mixed Platforms.Build.0 = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Release|Win32.ActiveCfg = Release|x86 {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Release|Win32.Build.0 = Release|x86 + {CB449DB5-9C97-447A-AA25-35EA7712F62C}.Release|x64.ActiveCfg = Release|x86 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Debug_Dedicated|x64.Build.0 = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Debug|Win32.ActiveCfg = Debug|Win32 - {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Debug|Win32.Build.0 = Debug|Win32 + {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Debug|x64.ActiveCfg = Debug|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Mixed_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Mixed_Dedicated|Win32.ActiveCfg = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Mixed_Dedicated|Win32.Build.0 = Release|Win32 + {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Mixed|Mixed Platforms.ActiveCfg = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Mixed|Mixed Platforms.Build.0 = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Mixed|Win32.ActiveCfg = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Mixed|Win32.Build.0 = Release|Win32 + {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Mixed|x64.ActiveCfg = Release|Win32 + {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Mixed|x64.Build.0 = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Release_Dedicated|x64.Build.0 = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Release|Mixed Platforms.Build.0 = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Release|Win32.ActiveCfg = Release|Win32 {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Release|Win32.Build.0 = Release|Win32 + {55B0E2CA-E27A-47FC-BC92-21ABDC1044F5}.Release|x64.ActiveCfg = Release|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {B90BDC22-A891-4B33-B562-29D701F65DBD}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {B90BDC22-A891-4B33-B562-29D701F65DBD}.Debug_Dedicated|x64.Build.0 = Release|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Debug|Win32.ActiveCfg = Debug|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Debug|Win32.Build.0 = Debug|Win32 + {B90BDC22-A891-4B33-B562-29D701F65DBD}.Debug|x64.ActiveCfg = Debug|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Mixed_Dedicated|Win32.Build.0 = Mixed|Win32 + {B90BDC22-A891-4B33-B562-29D701F65DBD}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {B90BDC22-A891-4B33-B562-29D701F65DBD}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Mixed|Win32.ActiveCfg = Mixed|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Mixed|Win32.Build.0 = Mixed|Win32 + {B90BDC22-A891-4B33-B562-29D701F65DBD}.Mixed|x64.ActiveCfg = Mixed|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {B90BDC22-A891-4B33-B562-29D701F65DBD}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {B90BDC22-A891-4B33-B562-29D701F65DBD}.Release_Dedicated|x64.Build.0 = Release|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Release|Mixed Platforms.Build.0 = Release|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Release|Win32.ActiveCfg = Release|Win32 {B90BDC22-A891-4B33-B562-29D701F65DBD}.Release|Win32.Build.0 = Release|Win32 + {B90BDC22-A891-4B33-B562-29D701F65DBD}.Release|x64.ActiveCfg = Release|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Debug_Dedicated|x64.Build.0 = Release|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Debug|Win32.ActiveCfg = Debug|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Debug|Win32.Build.0 = Debug|Win32 + {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Debug|x64.ActiveCfg = Debug|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Mixed_Dedicated|Win32.Build.0 = Mixed|Win32 + {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Mixed|Win32.ActiveCfg = Mixed|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Mixed|Win32.Build.0 = Mixed|Win32 + {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Mixed|x64.ActiveCfg = Mixed|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Release_Dedicated|x64.Build.0 = Release|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Release|Mixed Platforms.Build.0 = Release|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Release|Win32.ActiveCfg = Release|Win32 {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Release|Win32.Build.0 = Release|Win32 + {5CB057D8-4464-40A6-AF10-C26B826D1D90}.Release|x64.ActiveCfg = Release|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Debug_Dedicated|x64.Build.0 = Release|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Debug|Win32.ActiveCfg = Debug|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Debug|Win32.Build.0 = Debug|Win32 + {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Debug|x64.ActiveCfg = Debug|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Mixed_Dedicated|Win32.Build.0 = Mixed|Win32 + {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Mixed_Dedicated|x64.Build.0 = Release|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Mixed|Win32.ActiveCfg = Mixed|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Mixed|Win32.Build.0 = Mixed|Win32 + {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Mixed|x64.ActiveCfg = Mixed|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Release_Dedicated|x64.Build.0 = Release|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Release|Mixed Platforms.Build.0 = Release|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Release|Win32.ActiveCfg = Release|Win32 {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Release|Win32.Build.0 = Release|Win32 + {132C62DE-DE85-4978-9675-C78ED4DA46F0}.Release|x64.ActiveCfg = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Debug_Dedicated|Mixed Platforms.ActiveCfg = Debug|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Debug_Dedicated|Mixed Platforms.Build.0 = Debug|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Debug_Dedicated|Win32.ActiveCfg = Debug|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Debug_Dedicated|Win32.Build.0 = Debug|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Debug_Dedicated|x64.ActiveCfg = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Debug_Dedicated|x64.Build.0 = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Debug|Win32.ActiveCfg = Debug|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Debug|Win32.Build.0 = Debug|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Debug|x64.ActiveCfg = Debug|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Mixed_Dedicated|Mixed Platforms.ActiveCfg = Mixed|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Mixed_Dedicated|Mixed Platforms.Build.0 = Mixed|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Mixed_Dedicated|Win32.ActiveCfg = Mixed|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Mixed_Dedicated|Win32.Build.0 = Mixed|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Mixed_Dedicated|x64.ActiveCfg = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Mixed_Dedicated|x64.Build.0 = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Mixed|Mixed Platforms.ActiveCfg = Mixed|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Mixed|Mixed Platforms.Build.0 = Mixed|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Mixed|Win32.ActiveCfg = Mixed|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Mixed|Win32.Build.0 = Mixed|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Mixed|x64.ActiveCfg = Mixed|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Release_Dedicated|Mixed Platforms.ActiveCfg = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Release_Dedicated|Mixed Platforms.Build.0 = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Release_Dedicated|Win32.ActiveCfg = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Release_Dedicated|Win32.Build.0 = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Release_Dedicated|x64.ActiveCfg = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Release_Dedicated|x64.Build.0 = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Release|Mixed Platforms.Build.0 = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Release|Win32.ActiveCfg = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Release|Win32.Build.0 = Release|Win32 + {2C5AF8C8-96A6-45B2-860B-5E9C9911DDD6}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE