2013-10-18 09:55:43 +04:00
/*
2014-01-14 02:45:18 +04:00
* Copyright 2013 - 2014 Dario Manesku . All rights reserved .
2016-01-01 11:11:04 +03:00
* License : https : //github.com/bkaradzic/bgfx#license-bsd-2-clause
2013-10-18 09:55:43 +04:00
*/
2013-12-24 10:36:30 +04:00
# include <string>
# include <vector>
# include <map>
2014-08-22 18:35:30 +04:00
# include <tinystl/allocator.h>
# include <tinystl/unordered_map.h>
namespace stl = tinystl ;
2013-12-24 10:36:30 +04:00
2013-10-18 09:55:43 +04:00
# include "common.h"
2015-01-23 08:01:09 +03:00
# include "bgfx_utils.h"
2013-10-18 09:55:43 +04:00
2015-09-19 06:16:24 +03:00
# include <bgfx/bgfx.h>
2013-10-18 09:55:43 +04:00
# include <bx/timer.h>
2013-11-13 20:53:44 +04:00
# include <bx/allocator.h>
2013-11-20 23:28:12 +04:00
# include <bx/hash.h>
2016-07-19 05:03:25 +03:00
# include <bx/simd_t.h>
2014-05-27 06:31:37 +04:00
# include <bx/fpumath.h>
2016-02-22 00:59:38 +03:00
# include <bx/crtimpl.h>
2013-10-18 09:55:43 +04:00
# include "entry/entry.h"
2014-04-17 06:51:25 +04:00
# include "camera.h"
2013-10-18 09:55:43 +04:00
# include "imgui/imgui.h"
2013-11-13 01:18:14 +04:00
# define SV_USE_SIMD 1
2013-10-25 01:36:16 +04:00
# define MAX_INSTANCE_COUNT 25
# define MAX_LIGHTS_COUNT 5
2013-11-13 01:20:50 +04:00
# define VIEWID_RANGE1_PASS0 1
2013-10-20 22:34:28 +04:00
# define VIEWID_RANGE1_RT_PASS1 2
# define VIEWID_RANGE15_PASS2 3
# define VIEWID_RANGE1_PASS3 20
2013-10-18 09:55:43 +04:00
struct PosNormalTexcoordVertex
{
float m_x ;
float m_y ;
float m_z ;
uint32_t m_normal ;
float m_u ;
float m_v ;
2014-08-18 04:20:15 +04:00
static void init ( )
{
ms_decl
. begin ( )
. add ( bgfx : : Attrib : : Position , 3 , bgfx : : AttribType : : Float )
. add ( bgfx : : Attrib : : Normal , 4 , bgfx : : AttribType : : Uint8 , true , true )
. add ( bgfx : : Attrib : : TexCoord0 , 2 , bgfx : : AttribType : : Float )
. end ( ) ;
}
static bgfx : : VertexDecl ms_decl ;
2013-10-18 09:55:43 +04:00
} ;
2014-08-18 04:20:15 +04:00
bgfx : : VertexDecl PosNormalTexcoordVertex : : ms_decl ;
2013-10-18 09:55:43 +04:00
static const float s_texcoord = 50.0f ;
2014-08-18 04:20:15 +04:00
static PosNormalTexcoordVertex s_hplaneVertices [ ] =
2013-10-18 09:55:43 +04:00
{
2017-04-01 07:01:08 +03:00
{ - 1.0f , 0.0f , 1.0f , encodeNormalRgba8 ( 0.0f , 1.0f , 0.0f ) , s_texcoord , s_texcoord } ,
{ 1.0f , 0.0f , 1.0f , encodeNormalRgba8 ( 0.0f , 1.0f , 0.0f ) , s_texcoord , 0.0f } ,
{ - 1.0f , 0.0f , - 1.0f , encodeNormalRgba8 ( 0.0f , 1.0f , 0.0f ) , 0.0f , s_texcoord } ,
{ 1.0f , 0.0f , - 1.0f , encodeNormalRgba8 ( 0.0f , 1.0f , 0.0f ) , 0.0f , 0.0f } ,
2013-10-18 09:55:43 +04:00
} ;
2014-08-18 04:20:15 +04:00
static PosNormalTexcoordVertex s_vplaneVertices [ ] =
2013-10-18 09:55:43 +04:00
{
2017-04-01 07:01:08 +03:00
{ - 1.0f , 1.0f , 0.0f , encodeNormalRgba8 ( 0.0f , 0.0f , - 1.0f ) , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 0.0f , encodeNormalRgba8 ( 0.0f , 0.0f , - 1.0f ) , 1.0f , 0.0f } ,
{ - 1.0f , - 1.0f , 0.0f , encodeNormalRgba8 ( 0.0f , 0.0f , - 1.0f ) , 0.0f , 1.0f } ,
{ 1.0f , - 1.0f , 0.0f , encodeNormalRgba8 ( 0.0f , 0.0f , - 1.0f ) , 0.0f , 0.0f } ,
2013-10-18 09:55:43 +04:00
} ;
2014-08-18 04:20:15 +04:00
static const uint16_t s_planeIndices [ ] =
2013-10-18 09:55:43 +04:00
{
0 , 1 , 2 ,
1 , 3 , 2 ,
} ;
2014-10-06 09:03:41 +04:00
static bool s_oglNdc = false ;
2014-02-14 11:14:49 +04:00
static float s_texelHalf = 0.0f ;
2013-10-18 09:55:43 +04:00
static uint32_t s_viewMask = 0 ;
2015-06-08 07:28:36 +03:00
static bgfx : : UniformHandle s_texColor ;
static bgfx : : UniformHandle s_texStencil ;
2014-02-06 11:07:11 +04:00
static bgfx : : FrameBufferHandle s_stencilFb ;
2013-10-18 09:55:43 +04:00
2014-09-27 22:43:05 +04:00
void setViewClearMask ( uint32_t _viewMask , uint8_t _flags , uint32_t _rgba , float _depth , uint8_t _stencil )
{
for ( uint32_t view = 0 , viewMask = _viewMask , ntz = bx : : uint32_cnttz ( _viewMask ) ; 0 ! = viewMask ; viewMask > > = 1 , view + = 1 , ntz = bx : : uint32_cnttz ( viewMask ) )
{
viewMask > > = ntz ;
view + = ntz ;
bgfx : : setViewClear ( ( uint8_t ) view , _flags , _rgba , _depth , _stencil ) ;
}
}
void setViewTransformMask ( uint32_t _viewMask , const void * _view , const void * _proj )
{
for ( uint32_t view = 0 , viewMask = _viewMask , ntz = bx : : uint32_cnttz ( _viewMask ) ; 0 ! = viewMask ; viewMask > > = 1 , view + = 1 , ntz = bx : : uint32_cnttz ( viewMask ) )
{
viewMask > > = ntz ;
view + = ntz ;
bgfx : : setViewTransform ( ( uint8_t ) view , _view , _proj ) ;
}
}
void setViewRectMask ( uint32_t _viewMask , uint16_t _x , uint16_t _y , uint16_t _width , uint16_t _height )
{
for ( uint32_t view = 0 , viewMask = _viewMask , ntz = bx : : uint32_cnttz ( _viewMask ) ; 0 ! = viewMask ; viewMask > > = 1 , view + = 1 , ntz = bx : : uint32_cnttz ( viewMask ) )
{
viewMask > > = ntz ;
view + = ntz ;
bgfx : : setViewRect ( ( uint8_t ) view , _x , _y , _width , _height ) ;
}
}
2013-10-18 09:55:43 +04:00
void mtxBillboard ( float * __restrict _result
2013-10-20 22:34:28 +04:00
, const float * __restrict _view
, const float * __restrict _pos
, const float * __restrict _scale
)
2013-10-18 09:55:43 +04:00
{
_result [ 0 ] = _view [ 0 ] * _scale [ 0 ] ;
_result [ 1 ] = _view [ 4 ] * _scale [ 0 ] ;
_result [ 2 ] = _view [ 8 ] * _scale [ 0 ] ;
_result [ 3 ] = 0.0f ;
_result [ 4 ] = _view [ 1 ] * _scale [ 1 ] ;
_result [ 5 ] = _view [ 5 ] * _scale [ 1 ] ;
_result [ 6 ] = _view [ 9 ] * _scale [ 1 ] ;
_result [ 7 ] = 0.0f ;
_result [ 8 ] = _view [ 2 ] * _scale [ 2 ] ;
_result [ 9 ] = _view [ 6 ] * _scale [ 2 ] ;
_result [ 10 ] = _view [ 10 ] * _scale [ 2 ] ;
_result [ 11 ] = 0.0f ;
_result [ 12 ] = _pos [ 0 ] ;
_result [ 13 ] = _pos [ 1 ] ;
_result [ 14 ] = _pos [ 2 ] ;
_result [ 15 ] = 1.0f ;
}
void planeNormal ( float * __restrict _result
2013-10-20 22:34:28 +04:00
, const float * __restrict _v0
, const float * __restrict _v1
, const float * __restrict _v2
)
2013-10-18 09:55:43 +04:00
{
float vec0 [ 3 ] , vec1 [ 3 ] ;
float cross [ 3 ] ;
vec0 [ 0 ] = _v1 [ 0 ] - _v0 [ 0 ] ;
vec0 [ 1 ] = _v1 [ 1 ] - _v0 [ 1 ] ;
vec0 [ 2 ] = _v1 [ 2 ] - _v0 [ 2 ] ;
vec1 [ 0 ] = _v2 [ 0 ] - _v1 [ 0 ] ;
vec1 [ 1 ] = _v2 [ 1 ] - _v1 [ 1 ] ;
vec1 [ 2 ] = _v2 [ 2 ] - _v1 [ 2 ] ;
2014-05-27 06:31:37 +04:00
bx : : vec3Cross ( cross , vec0 , vec1 ) ;
bx : : vec3Norm ( _result , cross ) ;
2013-10-18 09:55:43 +04:00
2014-05-27 06:31:37 +04:00
_result [ 3 ] = - bx : : vec3Dot ( _result , _v0 ) ;
2013-10-18 09:55:43 +04:00
}
struct Uniforms
{
void init ( )
{
m_params . m_ambientPass = 1.0f ;
2015-11-30 02:39:16 +03:00
m_params . m_lightingPass = 1.0f ;
2014-02-14 11:14:49 +04:00
m_params . m_texelHalf = 0.0f ;
2013-10-18 09:55:43 +04:00
m_ambient [ 0 ] = 0.05f ;
m_ambient [ 1 ] = 0.05f ;
m_ambient [ 2 ] = 0.05f ;
m_ambient [ 3 ] = 0.0f ; //unused
m_diffuse [ 0 ] = 0.8f ;
m_diffuse [ 1 ] = 0.8f ;
m_diffuse [ 2 ] = 0.8f ;
m_diffuse [ 3 ] = 0.0f ; //unused
m_specular_shininess [ 0 ] = 1.0f ;
m_specular_shininess [ 1 ] = 1.0f ;
m_specular_shininess [ 2 ] = 1.0f ;
m_specular_shininess [ 3 ] = 25.0f ; //shininess
2013-10-20 22:34:28 +04:00
m_fog [ 0 ] = 0.0f ; //color
m_fog [ 1 ] = 0.0f ;
m_fog [ 2 ] = 0.0f ;
2013-10-18 09:55:43 +04:00
m_fog [ 3 ] = 0.0055f ; //density
m_color [ 0 ] = 1.0f ;
m_color [ 1 ] = 1.0f ;
m_color [ 2 ] = 1.0f ;
m_color [ 3 ] = 1.0f ;
m_time = 0.0f ;
m_lightPosRadius [ 0 ] = 0.0f ;
m_lightPosRadius [ 1 ] = 0.0f ;
m_lightPosRadius [ 2 ] = 0.0f ;
m_lightPosRadius [ 3 ] = 1.0f ;
m_lightRgbInnerR [ 0 ] = 0.0f ;
m_lightRgbInnerR [ 1 ] = 0.0f ;
m_lightRgbInnerR [ 2 ] = 0.0f ;
m_lightRgbInnerR [ 3 ] = 1.0f ;
m_virtualLightPos_extrusionDist [ 0 ] = 0.0f ;
m_virtualLightPos_extrusionDist [ 1 ] = 0.0f ;
m_virtualLightPos_extrusionDist [ 2 ] = 0.0f ;
m_virtualLightPos_extrusionDist [ 3 ] = 100.0f ;
2015-05-29 01:27:00 +03:00
u_params = bgfx : : createUniform ( " u_params " , bgfx : : UniformType : : Vec4 ) ;
u_svparams = bgfx : : createUniform ( " u_svparams " , bgfx : : UniformType : : Vec4 ) ;
u_ambient = bgfx : : createUniform ( " u_ambient " , bgfx : : UniformType : : Vec4 ) ;
u_diffuse = bgfx : : createUniform ( " u_diffuse " , bgfx : : UniformType : : Vec4 ) ;
u_specular_shininess = bgfx : : createUniform ( " u_specular_shininess " , bgfx : : UniformType : : Vec4 ) ;
u_fog = bgfx : : createUniform ( " u_fog " , bgfx : : UniformType : : Vec4 ) ;
u_color = bgfx : : createUniform ( " u_color " , bgfx : : UniformType : : Vec4 ) ;
u_lightPosRadius = bgfx : : createUniform ( " u_lightPosRadius " , bgfx : : UniformType : : Vec4 ) ;
u_lightRgbInnerR = bgfx : : createUniform ( " u_lightRgbInnerR " , bgfx : : UniformType : : Vec4 ) ;
u_virtualLightPos_extrusionDist = bgfx : : createUniform ( " u_virtualLightPos_extrusionDist " , bgfx : : UniformType : : Vec4 ) ;
2013-10-18 09:55:43 +04:00
}
//call this once at initialization
void submitConstUniforms ( )
{
bgfx : : setUniform ( u_ambient , & m_ambient ) ;
bgfx : : setUniform ( u_diffuse , & m_diffuse ) ;
bgfx : : setUniform ( u_specular_shininess , & m_specular_shininess ) ;
bgfx : : setUniform ( u_fog , & m_fog ) ;
}
//call this before each draw call
void submitPerDrawUniforms ( )
{
bgfx : : setUniform ( u_params , & m_params ) ;
bgfx : : setUniform ( u_svparams , & m_svparams ) ;
bgfx : : setUniform ( u_color , & m_color ) ;
bgfx : : setUniform ( u_lightPosRadius , & m_lightPosRadius ) ;
bgfx : : setUniform ( u_lightRgbInnerR , & m_lightRgbInnerR ) ;
bgfx : : setUniform ( u_virtualLightPos_extrusionDist , & m_virtualLightPos_extrusionDist ) ;
}
void destroy ( )
{
bgfx : : destroyUniform ( u_params ) ;
bgfx : : destroyUniform ( u_svparams ) ;
bgfx : : destroyUniform ( u_ambient ) ;
bgfx : : destroyUniform ( u_diffuse ) ;
bgfx : : destroyUniform ( u_specular_shininess ) ;
bgfx : : destroyUniform ( u_fog ) ;
bgfx : : destroyUniform ( u_color ) ;
bgfx : : destroyUniform ( u_lightPosRadius ) ;
bgfx : : destroyUniform ( u_lightRgbInnerR ) ;
bgfx : : destroyUniform ( u_virtualLightPos_extrusionDist ) ;
}
2013-10-20 22:34:28 +04:00
struct Params
2013-10-18 09:55:43 +04:00
{
float m_ambientPass ;
2015-11-30 02:39:16 +03:00
float m_lightingPass ;
2014-02-14 11:14:49 +04:00
float m_texelHalf ;
float m_unused00 ;
2013-10-20 22:34:28 +04:00
} ;
2013-11-13 01:20:50 +04:00
2013-10-20 22:34:28 +04:00
struct SvParams
2013-10-18 09:55:43 +04:00
{
float m_useStencilTex ;
float m_dfail ;
2014-02-14 11:14:49 +04:00
float m_unused10 ;
float m_unused11 ;
2013-10-20 22:34:28 +04:00
} ;
Params m_params ;
SvParams m_svparams ;
2013-10-18 09:55:43 +04:00
float m_ambient [ 4 ] ;
float m_diffuse [ 4 ] ;
float m_specular_shininess [ 4 ] ;
float m_fog [ 4 ] ;
float m_color [ 4 ] ;
float m_time ;
float m_lightPosRadius [ 4 ] ;
float m_lightRgbInnerR [ 4 ] ;
float m_virtualLightPos_extrusionDist [ 4 ] ;
/**
* u_params . x - u_ambientPass
2015-11-30 02:39:16 +03:00
* u_params . y - u_lightingPass
2014-02-14 11:14:49 +04:00
* u_params . z - u_texelHalf
* u_params . w - unused
2013-10-18 09:55:43 +04:00
* u_svparams . x - u_useStencilTex
* u_svparams . y - u_dfail
* u_svparams . z - unused
* u_svparams . w - unused
*/
bgfx : : UniformHandle u_params ;
bgfx : : UniformHandle u_svparams ;
bgfx : : UniformHandle u_ambient ;
bgfx : : UniformHandle u_diffuse ;
bgfx : : UniformHandle u_specular_shininess ;
bgfx : : UniformHandle u_fog ;
bgfx : : UniformHandle u_color ;
bgfx : : UniformHandle u_lightPosRadius ;
bgfx : : UniformHandle u_lightRgbInnerR ;
bgfx : : UniformHandle u_virtualLightPos_extrusionDist ;
} ;
2013-10-20 22:34:28 +04:00
static Uniforms s_uniforms ;
2013-10-18 09:55:43 +04:00
struct RenderState
{
enum Enum
{
ShadowVolume_UsingStencilTexture_DrawAmbient = 0 ,
ShadowVolume_UsingStencilTexture_BuildDepth ,
ShadowVolume_UsingStencilTexture_CraftStencil_DepthPass ,
ShadowVolume_UsingStencilTexture_CraftStencil_DepthFail ,
ShadowVolume_UsingStencilTexture_DrawDiffuse ,
ShadowVolume_UsingStencilBuffer_DrawAmbient ,
ShadowVolume_UsingStencilBuffer_CraftStencil_DepthPass ,
ShadowVolume_UsingStencilBuffer_CraftStencil_DepthFail ,
ShadowVolume_UsingStencilBuffer_DrawDiffuse ,
Custom_Default ,
Custom_BlendLightTexture ,
Custom_DrawPlaneBottom ,
Custom_DrawShadowVolume_Lines ,
Count
} ;
uint64_t m_state ;
uint32_t m_blendFactorRgba ;
uint32_t m_fstencil ;
uint32_t m_bstencil ;
} ;
static void setRenderState ( const RenderState & _renderState )
{
bgfx : : setStencil ( _renderState . m_fstencil , _renderState . m_bstencil ) ;
bgfx : : setState ( _renderState . m_state , _renderState . m_blendFactorRgba ) ;
}
static RenderState s_renderStates [ RenderState : : Count ] =
{
2013-10-20 22:34:28 +04:00
{ // ShadowVolume_UsingStencilTexture_DrawAmbient
2013-10-18 09:55:43 +04:00
BGFX_STATE_RGB_WRITE
2013-10-20 22:34:28 +04:00
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_DEPTH_WRITE
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_CULL_CCW
| BGFX_STATE_MSAA
, UINT32_MAX
, BGFX_STENCIL_NONE
, BGFX_STENCIL_NONE
2013-10-18 09:55:43 +04:00
} ,
2013-10-20 22:34:28 +04:00
{ // ShadowVolume_UsingStencilTexture_BuildDepth
2013-10-18 09:55:43 +04:00
BGFX_STATE_DEPTH_WRITE
2013-10-20 22:34:28 +04:00
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_CULL_CCW
| BGFX_STATE_MSAA
, UINT32_MAX
, BGFX_STENCIL_NONE
, BGFX_STENCIL_NONE
2013-10-18 09:55:43 +04:00
} ,
2013-10-20 22:34:28 +04:00
{ // ShadowVolume_UsingStencilTexture_CraftStencil_DepthPass
2013-10-18 09:55:43 +04:00
BGFX_STATE_RGB_WRITE
2013-10-20 22:34:28 +04:00
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_BLEND_FUNC ( BGFX_STATE_BLEND_ONE , BGFX_STATE_BLEND_ONE )
| BGFX_STATE_DEPTH_TEST_LEQUAL
| BGFX_STATE_MSAA
, UINT32_MAX
, BGFX_STENCIL_NONE
, BGFX_STENCIL_NONE
2013-10-18 09:55:43 +04:00
} ,
2013-10-20 22:34:28 +04:00
{ // ShadowVolume_UsingStencilTexture_CraftStencil_DepthFail
2013-10-18 09:55:43 +04:00
BGFX_STATE_RGB_WRITE
2013-10-20 22:34:28 +04:00
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_BLEND_FUNC ( BGFX_STATE_BLEND_ONE , BGFX_STATE_BLEND_ONE )
| BGFX_STATE_DEPTH_TEST_GEQUAL
| BGFX_STATE_MSAA
, UINT32_MAX
, BGFX_STENCIL_NONE
, BGFX_STENCIL_NONE
} ,
{ // ShadowVolume_UsingStencilTexture_DrawDiffuse
2013-10-18 09:55:43 +04:00
BGFX_STATE_RGB_WRITE
2013-10-20 22:34:28 +04:00
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_BLEND_FUNC ( BGFX_STATE_BLEND_ONE , BGFX_STATE_BLEND_ONE )
| BGFX_STATE_DEPTH_WRITE
| BGFX_STATE_DEPTH_TEST_EQUAL
| BGFX_STATE_CULL_CCW
| BGFX_STATE_MSAA
, UINT32_MAX
, BGFX_STENCIL_NONE
, BGFX_STENCIL_NONE
2013-10-18 09:55:43 +04:00
} ,
2013-10-20 22:34:28 +04:00
{ // ShadowVolume_UsingStencilBuffer_DrawAmbient
2013-10-18 09:55:43 +04:00
BGFX_STATE_RGB_WRITE
2013-10-20 22:34:28 +04:00
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_DEPTH_WRITE
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_CULL_CCW
| BGFX_STATE_MSAA
, UINT32_MAX
, BGFX_STENCIL_NONE
, BGFX_STENCIL_NONE
2013-10-18 09:55:43 +04:00
} ,
2013-10-20 22:34:28 +04:00
{ // ShadowVolume_UsingStencilBuffer_CraftStencil_DepthPass
2013-10-18 09:55:43 +04:00
BGFX_STATE_DEPTH_TEST_LEQUAL
2013-10-20 22:34:28 +04:00
| BGFX_STATE_MSAA
, UINT32_MAX
, BGFX_STENCIL_TEST_ALWAYS
2013-11-13 01:20:50 +04:00
| BGFX_STENCIL_FUNC_REF ( 1 )
2013-10-20 22:34:28 +04:00
| BGFX_STENCIL_FUNC_RMASK ( 0xff )
| BGFX_STENCIL_OP_FAIL_S_KEEP
| BGFX_STENCIL_OP_FAIL_Z_KEEP
| BGFX_STENCIL_OP_PASS_Z_DECR
, BGFX_STENCIL_TEST_ALWAYS
2013-11-13 01:20:50 +04:00
| BGFX_STENCIL_FUNC_REF ( 1 )
2013-10-20 22:34:28 +04:00
| BGFX_STENCIL_FUNC_RMASK ( 0xff )
| BGFX_STENCIL_OP_FAIL_S_KEEP
| BGFX_STENCIL_OP_FAIL_Z_KEEP
| BGFX_STENCIL_OP_PASS_Z_INCR
2013-10-18 09:55:43 +04:00
} ,
2013-10-20 22:34:28 +04:00
{ // ShadowVolume_UsingStencilBuffer_CraftStencil_DepthFail
2013-10-18 09:55:43 +04:00
BGFX_STATE_DEPTH_TEST_LEQUAL
2013-10-20 22:34:28 +04:00
| BGFX_STATE_MSAA
, UINT32_MAX
, BGFX_STENCIL_TEST_ALWAYS
2013-11-13 01:20:50 +04:00
| BGFX_STENCIL_FUNC_REF ( 1 )
2013-10-20 22:34:28 +04:00
| BGFX_STENCIL_FUNC_RMASK ( 0xff )
| BGFX_STENCIL_OP_FAIL_S_KEEP
| BGFX_STENCIL_OP_FAIL_Z_INCR
| BGFX_STENCIL_OP_PASS_Z_KEEP
, BGFX_STENCIL_TEST_ALWAYS
2013-11-13 01:20:50 +04:00
| BGFX_STENCIL_FUNC_REF ( 1 )
2013-10-20 22:34:28 +04:00
| BGFX_STENCIL_FUNC_RMASK ( 0xff )
| BGFX_STENCIL_OP_FAIL_S_KEEP
| BGFX_STENCIL_OP_FAIL_Z_DECR
| BGFX_STENCIL_OP_PASS_Z_KEEP
2013-10-18 09:55:43 +04:00
} ,
2013-10-20 22:34:28 +04:00
{ // ShadowVolume_UsingStencilBuffer_DrawDiffuse
BGFX_STATE_RGB_WRITE
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_BLEND_FUNC ( BGFX_STATE_BLEND_ONE , BGFX_STATE_BLEND_ONE )
| BGFX_STATE_DEPTH_TEST_EQUAL
| BGFX_STATE_CULL_CCW
| BGFX_STATE_MSAA
, UINT32_MAX
, BGFX_STENCIL_TEST_EQUAL
| BGFX_STENCIL_FUNC_REF ( 0 )
| BGFX_STENCIL_FUNC_RMASK ( 0xff )
| BGFX_STENCIL_OP_FAIL_S_KEEP
| BGFX_STENCIL_OP_FAIL_Z_KEEP
| BGFX_STENCIL_OP_PASS_Z_KEEP
, BGFX_STENCIL_NONE
2013-10-18 09:55:43 +04:00
} ,
2013-10-20 22:34:28 +04:00
{ // Custom_Default
2013-10-18 09:55:43 +04:00
BGFX_STATE_RGB_WRITE
2013-10-20 22:34:28 +04:00
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_DEPTH_WRITE
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_CULL_CCW
| BGFX_STATE_MSAA
, UINT32_MAX
, BGFX_STENCIL_NONE
, BGFX_STENCIL_NONE
2013-10-18 09:55:43 +04:00
} ,
2013-10-20 22:34:28 +04:00
{ // Custom_BlendLightTexture
2013-10-18 09:55:43 +04:00
BGFX_STATE_RGB_WRITE
2013-10-20 22:34:28 +04:00
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_DEPTH_WRITE
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_BLEND_FUNC ( BGFX_STATE_BLEND_SRC_COLOR , BGFX_STATE_BLEND_INV_SRC_COLOR )
| BGFX_STATE_CULL_CCW
| BGFX_STATE_MSAA
, UINT32_MAX
, BGFX_STENCIL_NONE
, BGFX_STENCIL_NONE
2013-10-18 09:55:43 +04:00
} ,
2013-10-20 22:34:28 +04:00
{ // Custom_DrawPlaneBottom
2013-10-18 09:55:43 +04:00
BGFX_STATE_RGB_WRITE
2013-10-20 22:34:28 +04:00
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_DEPTH_WRITE
| BGFX_STATE_CULL_CW
| BGFX_STATE_MSAA
, UINT32_MAX
, BGFX_STENCIL_NONE
, BGFX_STENCIL_NONE
2013-10-18 09:55:43 +04:00
} ,
2013-10-20 22:34:28 +04:00
{ // Custom_DrawShadowVolume_Lines
2013-10-18 09:55:43 +04:00
BGFX_STATE_RGB_WRITE
2013-10-20 22:34:28 +04:00
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_BLEND_FUNC ( BGFX_STATE_BLEND_FACTOR , BGFX_STATE_BLEND_SRC_ALPHA )
| BGFX_STATE_PT_LINES
| BGFX_STATE_MSAA
, 0x0f0f0fff
, BGFX_STENCIL_NONE
, BGFX_STENCIL_NONE
2013-10-18 09:55:43 +04:00
}
} ;
struct ViewState
{
2013-10-29 05:35:47 +04:00
ViewState ( uint32_t _width = 1280 , uint32_t _height = 720 )
2013-10-18 09:55:43 +04:00
: m_width ( _width )
, m_height ( _height )
2013-10-20 22:34:28 +04:00
{
}
2013-10-18 09:55:43 +04:00
uint32_t m_width ;
uint32_t m_height ;
2013-10-21 06:30:58 +04:00
float m_view [ 16 ] ;
float m_proj [ 16 ] ;
2013-10-18 09:55:43 +04:00
} ;
struct ClearValues
{
uint32_t m_clearRgba ;
float m_clearDepth ;
uint8_t m_clearStencil ;
} ;
2015-07-23 04:05:11 +03:00
void submit ( uint8_t _id , bgfx : : ProgramHandle _handle , int32_t _depth = 0 )
2013-10-18 09:55:43 +04:00
{
2015-07-23 04:05:11 +03:00
bgfx : : submit ( _id , _handle , _depth ) ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
// Keep track of submited view ids.
2013-10-18 09:55:43 +04:00
s_viewMask | = 1 < < _id ;
}
2015-07-23 04:05:11 +03:00
void touch ( uint8_t _id )
{
bgfx : : ProgramHandle handle = BGFX_INVALID_HANDLE ;
: : submit ( _id , handle ) ;
}
2013-10-18 09:55:43 +04:00
struct Aabb
{
float m_min [ 3 ] ;
float m_max [ 3 ] ;
} ;
struct Obb
{
float m_mtx [ 16 ] ;
} ;
struct Sphere
{
float m_center [ 3 ] ;
float m_radius ;
} ;
struct Primitive
{
uint32_t m_startIndex ;
uint32_t m_numIndices ;
uint32_t m_startVertex ;
uint32_t m_numVertices ;
Sphere m_sphere ;
Aabb m_aabb ;
Obb m_obb ;
} ;
typedef std : : vector < Primitive > PrimitiveArray ;
struct Face
{
uint16_t m_i [ 3 ] ;
float m_plane [ 4 ] ;
} ;
typedef std : : vector < Face > FaceArray ;
struct Edge
{
2013-11-13 01:18:14 +04:00
bool m_faceReverseOrder [ 2 ] ;
2013-10-18 09:55:43 +04:00
uint8_t m_faceIndex ;
2013-11-20 23:28:12 +04:00
uint16_t m_i0 , m_i1 ;
2013-10-18 09:55:43 +04:00
} ;
2013-11-13 20:53:44 +04:00
struct Plane
{
float m_plane [ 4 ] ;
} ;
2013-10-18 09:55:43 +04:00
struct HalfEdge
{
# define INVALID_EDGE_INDEX UINT16_MAX
uint16_t m_secondIndex ;
bool m_marked ;
} ;
struct HalfEdges
{
HalfEdges ( )
: m_data ( )
, m_offsets ( )
, m_endPtr ( )
2013-10-20 22:34:28 +04:00
{
}
2013-10-18 09:55:43 +04:00
void init ( uint16_t * _indices , uint32_t _numIndices )
{
2013-10-20 22:34:28 +04:00
m_data = ( HalfEdge * ) malloc ( 2 * _numIndices * sizeof ( HalfEdge ) ) ;
2013-10-18 09:55:43 +04:00
2014-08-22 18:35:30 +04:00
stl : : unordered_map < uint16_t , std : : vector < uint16_t > > edges ;
2013-10-18 09:55:43 +04:00
for ( uint32_t ii = 0 ; ii < _numIndices ; ii + = 3 )
{
uint16_t idx0 = _indices [ ii ] ;
uint16_t idx1 = _indices [ ii + 1 ] ;
uint16_t idx2 = _indices [ ii + 2 ] ;
edges [ idx0 ] . push_back ( idx1 ) ;
edges [ idx1 ] . push_back ( idx2 ) ;
edges [ idx2 ] . push_back ( idx0 ) ;
}
2013-10-19 10:45:34 +04:00
uint32_t numRows = ( uint32_t ) edges . size ( ) ;
2013-10-20 22:34:28 +04:00
m_offsets = ( uint32_t * ) malloc ( numRows * sizeof ( uint32_t ) ) ;
2013-10-18 09:55:43 +04:00
HalfEdge * he = m_data ;
2017-03-13 04:25:23 +03:00
for ( uint16_t ii = 0 ; ii < numRows ; + + ii )
2013-10-18 09:55:43 +04:00
{
m_offsets [ ii ] = uint32_t ( he - m_data ) ;
std : : vector < uint16_t > & row = edges [ ii ] ;
2015-04-05 05:10:35 +03:00
for ( uint32_t jj = 0 , size = ( uint32_t ) row . size ( ) ; jj < size ; + + jj )
2013-10-18 09:55:43 +04:00
{
he - > m_secondIndex = row [ jj ] ;
he - > m_marked = false ;
+ + he ;
}
he - > m_secondIndex = INVALID_EDGE_INDEX ;
+ + he ;
}
he - > m_secondIndex = 0 ;
m_endPtr = he ;
}
2013-10-20 22:34:28 +04:00
2013-10-18 09:55:43 +04:00
void destroy ( )
{
free ( m_data ) ;
m_data = NULL ;
free ( m_offsets ) ;
m_offsets = NULL ;
}
void mark ( uint16_t _firstIndex , uint16_t _secondIndex )
{
HalfEdge * ptr = & m_data [ m_offsets [ _firstIndex ] ] ;
while ( INVALID_EDGE_INDEX ! = ptr - > m_secondIndex )
{
if ( ptr - > m_secondIndex = = _secondIndex )
{
ptr - > m_marked = true ;
break ;
}
+ + ptr ;
}
}
bool unmark ( uint16_t _firstIndex , uint16_t _secondIndex )
{
bool ret = false ;
HalfEdge * ptr = & m_data [ m_offsets [ _firstIndex ] ] ;
while ( INVALID_EDGE_INDEX ! = ptr - > m_secondIndex )
{
if ( ptr - > m_secondIndex = = _secondIndex & & ptr - > m_marked )
{
ptr - > m_marked = false ;
ret = true ;
break ;
}
+ + ptr ;
}
return ret ;
}
2013-10-20 22:34:28 +04:00
inline HalfEdge * begin ( ) const
{
return m_data ;
}
inline HalfEdge * end ( ) const
{
return m_endPtr ;
}
2013-10-18 09:55:43 +04:00
HalfEdge * m_data ;
uint32_t * m_offsets ;
HalfEdge * m_endPtr ;
} ;
2013-11-20 23:28:12 +04:00
struct WeldedVertex
{
uint16_t m_v ;
bool m_welded ;
} ;
inline float sqLength ( const float _a [ 3 ] , const float _b [ 3 ] )
{
const float xx = _a [ 0 ] - _b [ 0 ] ;
const float yy = _a [ 1 ] - _b [ 1 ] ;
const float zz = _a [ 2 ] - _b [ 2 ] ;
return xx * xx + yy * yy + zz * zz ;
}
uint16_t weldVertices ( WeldedVertex * _output , const bgfx : : VertexDecl & _decl , const void * _data , uint16_t _num , float _epsilon )
{
const uint32_t hashSize = bx : : uint32_nextpow2 ( _num ) ;
const uint32_t hashMask = hashSize - 1 ;
const float epsilonSq = _epsilon * _epsilon ;
2017-03-13 04:25:23 +03:00
uint16_t numVertices = 0 ;
2013-11-20 23:28:12 +04:00
const uint32_t size = sizeof ( uint16_t ) * ( hashSize + _num ) ;
uint16_t * hashTable = ( uint16_t * ) alloca ( size ) ;
2017-02-09 06:55:31 +03:00
bx : : memSet ( hashTable , 0xff , size ) ;
2013-11-20 23:28:12 +04:00
uint16_t * next = hashTable + hashSize ;
2017-03-13 04:25:23 +03:00
for ( uint16_t ii = 0 ; ii < _num ; + + ii )
2013-11-20 23:28:12 +04:00
{
float pos [ 4 ] ;
vertexUnpack ( pos , bgfx : : Attrib : : Position , _decl , _data , ii ) ;
uint32_t hashValue = bx : : hashMurmur2A ( pos , 3 * sizeof ( float ) ) & hashMask ;
uint16_t offset = hashTable [ hashValue ] ;
for ( ; UINT16_MAX ! = offset ; offset = next [ offset ] )
{
float test [ 4 ] ;
vertexUnpack ( test , bgfx : : Attrib : : Position , _decl , _data , _output [ offset ] . m_v ) ;
if ( sqLength ( test , pos ) < epsilonSq )
{
_output [ ii ] . m_v = _output [ offset ] . m_v ;
_output [ ii ] . m_welded = true ;
break ;
}
}
if ( UINT16_MAX = = offset )
{
_output [ ii ] . m_v = ii ;
_output [ ii ] . m_welded = false ;
next [ ii ] = hashTable [ hashValue ] ;
hashTable [ hashValue ] = ii ;
numVertices + + ;
}
}
return numVertices ;
}
2013-10-18 09:55:43 +04:00
struct Group
{
Group ( )
{
reset ( ) ;
}
void reset ( )
{
2017-06-10 07:57:08 +03:00
m_vbh . idx = bgfx : : kInvalidHandle ;
m_ibh . idx = bgfx : : kInvalidHandle ;
2013-10-18 09:55:43 +04:00
m_numVertices = 0 ;
m_vertices = NULL ;
m_numIndices = 0 ;
m_indices = NULL ;
2013-11-13 01:18:14 +04:00
m_numEdges = 0 ;
m_edges = NULL ;
2013-11-13 20:53:44 +04:00
m_edgePlanesUnalignedPtr = NULL ;
2013-10-18 09:55:43 +04:00
m_prims . clear ( ) ;
}
2013-11-13 01:18:14 +04:00
typedef struct { float f [ 6 ] ; } f6_t ;
2013-11-18 05:57:39 +04:00
struct EdgeAndPlane
2013-11-13 01:18:14 +04:00
{
2013-11-20 23:28:12 +04:00
EdgeAndPlane ( uint16_t _i0 , uint16_t _i1 )
2013-11-18 05:57:39 +04:00
: m_faceIndex ( 0 )
2013-11-20 23:28:12 +04:00
, m_i0 ( _i0 )
, m_i1 ( _i1 )
2013-11-13 01:18:14 +04:00
{
}
2013-11-18 05:57:39 +04:00
bool m_faceReverseOrder [ 2 ] ;
uint8_t m_faceIndex ;
2013-11-20 23:28:12 +04:00
uint16_t m_i0 , m_i1 ;
2013-11-18 05:57:39 +04:00
Plane m_plane [ 2 ] ;
2013-11-13 01:18:14 +04:00
} ;
2013-11-20 23:28:12 +04:00
void fillStructures ( const bgfx : : VertexDecl & _decl )
2013-10-18 09:55:43 +04:00
{
2013-11-20 23:28:12 +04:00
uint16_t stride = _decl . getStride ( ) ;
2013-10-18 09:55:43 +04:00
m_faces . clear ( ) ;
m_halfEdges . destroy ( ) ;
2013-11-20 23:28:12 +04:00
//Init halfedges.
2013-10-18 09:55:43 +04:00
m_halfEdges . init ( m_indices , m_numIndices ) ;
2013-11-20 23:28:12 +04:00
//Init faces and edges.
2013-11-13 01:18:14 +04:00
m_faces . reserve ( m_numIndices / 3 ) ; //1 face = 3 indices
2015-07-17 06:28:43 +03:00
m_edges = ( Edge * ) malloc ( m_numIndices * sizeof ( Edge ) ) ; //1 triangle = 3 indices = 3 edges.
2013-11-13 20:53:44 +04:00
m_edgePlanesUnalignedPtr = ( Plane * ) malloc ( m_numIndices * sizeof ( Plane ) + 15 ) ;
m_edgePlanes = ( Plane * ) bx : : alignPtr ( m_edgePlanesUnalignedPtr , 0 , 16 ) ;
2013-11-20 23:28:12 +04:00
typedef std : : map < std : : pair < uint16_t , uint16_t > , EdgeAndPlane > EdgeMap ;
2013-11-13 01:18:14 +04:00
EdgeMap edgeMap ;
2013-10-18 09:55:43 +04:00
2013-11-20 23:28:12 +04:00
//Get unique indices.
WeldedVertex * uniqueVertices = ( WeldedVertex * ) malloc ( m_numVertices * sizeof ( WeldedVertex ) ) ;
: : weldVertices ( uniqueVertices , _decl , m_vertices , m_numVertices , 0.0001f ) ;
uint16_t * uniqueIndices = ( uint16_t * ) malloc ( m_numIndices * sizeof ( uint16_t ) ) ;
for ( uint32_t ii = 0 ; ii < m_numIndices ; + + ii )
2013-11-13 20:53:44 +04:00
{
2013-11-20 23:28:12 +04:00
uint16_t index = m_indices [ ii ] ;
if ( uniqueVertices [ index ] . m_welded )
2013-11-13 20:53:44 +04:00
{
2013-11-20 23:28:12 +04:00
uniqueIndices [ ii ] = uniqueVertices [ index ] . m_v ;
2013-11-13 20:53:44 +04:00
}
2013-11-20 23:28:12 +04:00
else
{
uniqueIndices [ ii ] = index ;
}
}
free ( uniqueVertices ) ;
2013-10-18 09:55:43 +04:00
for ( uint32_t ii = 0 , size = m_numIndices / 3 ; ii < size ; + + ii )
{
const uint16_t * indices = & m_indices [ ii * 3 ] ;
2015-04-05 02:40:28 +03:00
uint16_t i0 = indices [ 0 ] ;
uint16_t i1 = indices [ 1 ] ;
uint16_t i2 = indices [ 2 ] ;
2013-11-20 23:28:12 +04:00
const float * v0 = ( float * ) & m_vertices [ i0 * stride ] ;
const float * v1 = ( float * ) & m_vertices [ i1 * stride ] ;
const float * v2 = ( float * ) & m_vertices [ i2 * stride ] ;
2013-10-18 09:55:43 +04:00
float plane [ 4 ] ;
planeNormal ( plane , v0 , v2 , v1 ) ;
Face face ;
face . m_i [ 0 ] = i0 ;
face . m_i [ 1 ] = i1 ;
face . m_i [ 2 ] = i2 ;
2017-02-09 06:55:31 +03:00
bx : : memCopy ( face . m_plane , plane , 4 * sizeof ( float ) ) ;
2013-10-18 09:55:43 +04:00
m_faces . push_back ( face ) ;
2013-11-20 23:28:12 +04:00
//Use unique indices for EdgeMap.
const uint16_t * uindices = & uniqueIndices [ ii * 3 ] ;
2015-04-05 02:40:28 +03:00
i0 = uindices [ 0 ] ;
i1 = uindices [ 1 ] ;
i2 = uindices [ 2 ] ;
2013-11-20 23:28:12 +04:00
const uint16_t triangleEdge [ 3 ] [ 2 ] =
2013-10-18 09:55:43 +04:00
{
2015-04-05 02:40:28 +03:00
{ i0 , i1 } ,
{ i1 , i2 } ,
{ i2 , i0 } ,
2013-10-18 09:55:43 +04:00
} ;
for ( uint8_t jj = 0 ; jj < 3 ; + + jj )
2013-11-13 01:18:14 +04:00
{
2013-11-20 23:28:12 +04:00
const uint16_t ui0 = triangleEdge [ jj ] [ 0 ] ;
const uint16_t ui1 = triangleEdge [ jj ] [ 1 ] ;
std : : pair < uint16_t , uint16_t > key = std : : make_pair ( ui0 , ui1 ) ;
std : : pair < uint16_t , uint16_t > keyInv = std : : make_pair ( ui1 , ui0 ) ;
2013-11-13 01:18:14 +04:00
EdgeMap : : iterator iter = edgeMap . find ( keyInv ) ;
2015-07-17 06:28:43 +03:00
if ( iter ! = edgeMap . end ( ) )
2013-10-18 09:55:43 +04:00
{
2013-11-13 20:53:44 +04:00
EdgeAndPlane & ep = iter - > second ;
2017-02-09 06:55:31 +03:00
bx : : memCopy ( ep . m_plane [ ep . m_faceIndex ] . m_plane , plane , 4 * sizeof ( float ) ) ;
2013-11-13 20:53:44 +04:00
ep . m_faceReverseOrder [ ep . m_faceIndex ] = true ;
2013-10-18 09:55:43 +04:00
}
else
{
2013-11-20 23:28:12 +04:00
std : : pair < EdgeMap : : iterator , bool > result = edgeMap . insert ( std : : make_pair ( key , EdgeAndPlane ( ui0 , ui1 ) ) ) ;
2013-11-13 20:53:44 +04:00
EdgeAndPlane & ep = result . first - > second ;
2017-02-09 06:55:31 +03:00
bx : : memCopy ( ep . m_plane [ ep . m_faceIndex ] . m_plane , plane , 4 * sizeof ( float ) ) ;
2013-11-13 20:53:44 +04:00
ep . m_faceReverseOrder [ ep . m_faceIndex ] = false ;
ep . m_faceIndex + + ;
2013-10-18 09:55:43 +04:00
}
}
2013-11-13 01:18:14 +04:00
}
2013-10-18 09:55:43 +04:00
2013-11-20 23:28:12 +04:00
free ( uniqueIndices ) ;
2013-11-13 20:53:44 +04:00
uint32_t index = 0 ;
2013-11-13 01:18:14 +04:00
for ( EdgeMap : : const_iterator iter = edgeMap . begin ( ) , end = edgeMap . end ( ) ; iter ! = end ; + + iter )
{
2013-11-13 20:53:44 +04:00
Edge * edge = & m_edges [ m_numEdges ] ;
Plane * plane = & m_edgePlanes [ index ] ;
2017-02-09 06:55:31 +03:00
bx : : memCopy ( edge , iter - > second . m_faceReverseOrder , sizeof ( Edge ) ) ;
bx : : memCopy ( plane , iter - > second . m_plane , 2 * sizeof ( Plane ) ) ;
2013-11-13 20:53:44 +04:00
m_numEdges + + ;
index + = 2 ;
2013-10-18 09:55:43 +04:00
}
}
void unload ( )
{
bgfx : : destroyVertexBuffer ( m_vbh ) ;
2017-06-10 07:57:08 +03:00
if ( bgfx : : kInvalidHandle ! = m_ibh . idx )
2013-10-18 09:55:43 +04:00
{
bgfx : : destroyIndexBuffer ( m_ibh ) ;
}
free ( m_vertices ) ;
m_vertices = NULL ;
free ( m_indices ) ;
m_indices = NULL ;
2013-11-13 01:18:14 +04:00
free ( m_edges ) ;
m_edges = NULL ;
2013-11-13 20:53:44 +04:00
free ( m_edgePlanesUnalignedPtr ) ;
m_edgePlanesUnalignedPtr = NULL ;
2013-10-18 09:55:43 +04:00
m_halfEdges . destroy ( ) ;
}
bgfx : : VertexBufferHandle m_vbh ;
bgfx : : IndexBufferHandle m_ibh ;
uint16_t m_numVertices ;
uint8_t * m_vertices ;
uint32_t m_numIndices ;
uint16_t * m_indices ;
Sphere m_sphere ;
Aabb m_aabb ;
Obb m_obb ;
PrimitiveArray m_prims ;
2013-11-13 01:18:14 +04:00
uint32_t m_numEdges ;
Edge * m_edges ;
2013-11-13 20:53:44 +04:00
Plane * m_edgePlanesUnalignedPtr ;
Plane * m_edgePlanes ;
2013-10-18 09:55:43 +04:00
FaceArray m_faces ;
HalfEdges m_halfEdges ;
} ;
2013-10-20 22:34:28 +04:00
2013-10-18 09:55:43 +04:00
typedef std : : vector < Group > GroupArray ;
2014-08-18 04:20:15 +04:00
namespace bgfx
{
2016-03-07 01:59:14 +03:00
int32_t read ( bx : : ReaderI * _reader , bgfx : : VertexDecl & _decl , bx : : Error * _err = NULL ) ;
2014-08-18 04:20:15 +04:00
}
2013-10-18 09:55:43 +04:00
struct Mesh
{
2017-03-13 04:25:23 +03:00
void load ( const void * _vertices , uint16_t _numVertices , const bgfx : : VertexDecl _decl , const uint16_t * _indices , uint32_t _numIndices )
2013-10-18 09:55:43 +04:00
{
Group group ;
const bgfx : : Memory * mem ;
uint32_t size ;
//vertices
group . m_numVertices = _numVertices ;
size = _numVertices * _decl . getStride ( ) ;
group . m_vertices = ( uint8_t * ) malloc ( size ) ;
2017-02-09 06:55:31 +03:00
bx : : memCopy ( group . m_vertices , _vertices , size ) ;
2013-10-18 09:55:43 +04:00
mem = bgfx : : makeRef ( group . m_vertices , size ) ;
group . m_vbh = bgfx : : createVertexBuffer ( mem , _decl ) ;
//indices
group . m_numIndices = _numIndices ;
size = _numIndices * 2 ;
group . m_indices = ( uint16_t * ) malloc ( size ) ;
2017-02-09 06:55:31 +03:00
bx : : memCopy ( group . m_indices , _indices , size ) ;
2013-10-18 09:55:43 +04:00
mem = bgfx : : makeRef ( group . m_indices , size ) ;
group . m_ibh = bgfx : : createIndexBuffer ( mem ) ;
m_groups . push_back ( group ) ;
}
void load ( const char * _filePath )
{
2014-08-18 04:20:15 +04:00
# define BGFX_CHUNK_MAGIC_VB BX_MAKEFOURCC('V', 'B', ' ', 0x1)
# define BGFX_CHUNK_MAGIC_IB BX_MAKEFOURCC('I', 'B', ' ', 0x0)
2013-10-18 09:55:43 +04:00
# define BGFX_CHUNK_MAGIC_PRI BX_MAKEFOURCC('P', 'R', 'I', 0x0)
2016-12-09 07:45:01 +03:00
bx : : FileReaderI * reader = entry : : getFileReader ( ) ;
bx : : open ( reader , _filePath ) ;
2013-10-18 09:55:43 +04:00
Group group ;
uint32_t chunk ;
2016-12-09 07:45:01 +03:00
while ( 4 = = bx : : read ( reader , chunk ) )
2013-10-18 09:55:43 +04:00
{
switch ( chunk )
{
2013-10-20 22:34:28 +04:00
case BGFX_CHUNK_MAGIC_VB :
{
2016-12-09 07:45:01 +03:00
bx : : read ( reader , group . m_sphere ) ;
bx : : read ( reader , group . m_aabb ) ;
bx : : read ( reader , group . m_obb ) ;
2013-10-18 09:55:43 +04:00
2016-12-09 07:45:01 +03:00
bgfx : : read ( reader , m_decl ) ;
2013-10-20 22:34:28 +04:00
uint16_t stride = m_decl . getStride ( ) ;
2013-10-18 09:55:43 +04:00
2016-12-09 07:45:01 +03:00
bx : : read ( reader , group . m_numVertices ) ;
2013-10-20 22:34:28 +04:00
const uint32_t size = group . m_numVertices * stride ;
group . m_vertices = ( uint8_t * ) malloc ( size ) ;
2016-12-09 07:45:01 +03:00
bx : : read ( reader , group . m_vertices , size ) ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
const bgfx : : Memory * mem = bgfx : : makeRef ( group . m_vertices , size ) ;
group . m_vbh = bgfx : : createVertexBuffer ( mem , m_decl ) ;
}
break ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
case BGFX_CHUNK_MAGIC_IB :
{
2016-12-09 07:45:01 +03:00
bx : : read ( reader , group . m_numIndices ) ;
2013-10-20 22:34:28 +04:00
const uint32_t size = group . m_numIndices * 2 ;
group . m_indices = ( uint16_t * ) malloc ( size ) ;
2016-12-09 07:45:01 +03:00
bx : : read ( reader , group . m_indices , size ) ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
const bgfx : : Memory * mem = bgfx : : makeRef ( group . m_indices , size ) ;
group . m_ibh = bgfx : : createIndexBuffer ( mem ) ;
}
break ;
case BGFX_CHUNK_MAGIC_PRI :
{
uint16_t len ;
2016-12-09 07:45:01 +03:00
bx : : read ( reader , len ) ;
2013-10-20 22:34:28 +04:00
std : : string material ;
material . resize ( len ) ;
2016-12-09 07:45:01 +03:00
bx : : read ( reader , const_cast < char * > ( material . c_str ( ) ) , len ) ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
uint16_t num ;
2016-12-09 07:45:01 +03:00
bx : : read ( reader , num ) ;
2013-10-20 22:34:28 +04:00
for ( uint32_t ii = 0 ; ii < num ; + + ii )
2013-10-18 09:55:43 +04:00
{
2016-12-09 07:45:01 +03:00
bx : : read ( reader , len ) ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
std : : string name ;
name . resize ( len ) ;
2016-12-09 07:45:01 +03:00
bx : : read ( reader , const_cast < char * > ( name . c_str ( ) ) , len ) ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
Primitive prim ;
2016-12-09 07:45:01 +03:00
bx : : read ( reader , prim . m_startIndex ) ;
bx : : read ( reader , prim . m_numIndices ) ;
bx : : read ( reader , prim . m_startVertex ) ;
bx : : read ( reader , prim . m_numVertices ) ;
bx : : read ( reader , prim . m_sphere ) ;
bx : : read ( reader , prim . m_aabb ) ;
bx : : read ( reader , prim . m_obb ) ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
group . m_prims . push_back ( prim ) ;
2013-10-18 09:55:43 +04:00
}
2013-10-20 22:34:28 +04:00
m_groups . push_back ( group ) ;
group . reset ( ) ;
}
break ;
default :
2016-12-09 07:45:01 +03:00
DBG ( " %08x at %d " , chunk , bx : : seek ( reader ) ) ;
2014-08-18 04:20:15 +04:00
abort ( ) ;
2013-10-20 22:34:28 +04:00
break ;
2013-10-18 09:55:43 +04:00
}
}
2016-12-09 07:45:01 +03:00
bx : : close ( reader ) ;
2013-10-18 09:55:43 +04:00
for ( GroupArray : : iterator it = m_groups . begin ( ) , itEnd = m_groups . end ( ) ; it ! = itEnd ; + + it )
{
2013-11-20 23:28:12 +04:00
it - > fillStructures ( m_decl ) ;
2013-10-18 09:55:43 +04:00
}
}
void unload ( )
{
for ( GroupArray : : iterator it = m_groups . begin ( ) , itEnd = m_groups . end ( ) ; it ! = itEnd ; + + it )
{
it - > unload ( ) ;
}
m_groups . clear ( ) ;
}
bgfx : : VertexDecl m_decl ;
GroupArray m_groups ;
} ;
struct Model
{
Model ( )
2013-11-13 01:20:50 +04:00
{
2017-06-10 07:57:08 +03:00
m_program . idx = bgfx : : kInvalidHandle ;
m_texture . idx = bgfx : : kInvalidHandle ;
2013-10-18 09:55:43 +04:00
}
2017-03-13 04:25:23 +03:00
void load ( const void * _vertices , uint16_t _numVertices , const bgfx : : VertexDecl _decl , const uint16_t * _indices , uint32_t _numIndices )
2013-10-18 09:55:43 +04:00
{
m_mesh . load ( _vertices , _numVertices , _decl , _indices , _numIndices ) ;
}
void load ( const char * _meshFilePath )
{
m_mesh . load ( _meshFilePath ) ;
}
void unload ( )
{
m_mesh . unload ( ) ;
}
void submit ( uint8_t _viewId , float * _mtx , const RenderState & _renderState )
{
for ( GroupArray : : const_iterator it = m_mesh . m_groups . begin ( ) , itEnd = m_mesh . m_groups . end ( ) ; it ! = itEnd ; + + it )
{
const Group & group = * it ;
// Set uniforms
s_uniforms . submitPerDrawUniforms ( ) ;
// Set transform
bgfx : : setTransform ( _mtx ) ;
// Set buffers
bgfx : : setIndexBuffer ( group . m_ibh ) ;
2017-05-14 21:48:59 +03:00
bgfx : : setVertexBuffer ( 0 , group . m_vbh ) ;
2013-10-18 09:55:43 +04:00
// Set textures
2017-06-10 07:57:08 +03:00
if ( bgfx : : kInvalidHandle ! = m_texture . idx )
2013-10-18 09:55:43 +04:00
{
2015-06-08 07:28:36 +03:00
bgfx : : setTexture ( 0 , s_texColor , m_texture ) ;
2013-10-18 09:55:43 +04:00
}
2016-11-16 07:23:52 +03:00
bgfx : : setTexture ( 1 , s_texStencil , bgfx : : getTexture ( s_stencilFb ) ) ;
2013-10-18 09:55:43 +04:00
// Apply render state
: : setRenderState ( _renderState ) ;
// Submit
2017-06-10 07:57:08 +03:00
BX_CHECK ( bgfx : : kInvalidHandle ! = m_program , " Error, program is not set. " ) ;
2015-07-23 04:05:11 +03:00
: : submit ( _viewId , m_program ) ;
2013-10-18 09:55:43 +04:00
}
}
Mesh m_mesh ;
bgfx : : ProgramHandle m_program ;
bgfx : : TextureHandle m_texture ;
} ;
struct Instance
{
Instance ( )
: m_svExtrusionDistance ( 150.0f )
2013-11-13 01:20:50 +04:00
{
2013-10-18 09:55:43 +04:00
m_color [ 0 ] = 1.0f ;
m_color [ 1 ] = 1.0f ;
m_color [ 2 ] = 1.0f ;
}
void submit ( uint8_t _viewId , const RenderState & _renderState )
{
2017-02-09 06:55:31 +03:00
bx : : memCopy ( s_uniforms . m_color , m_color , 3 * sizeof ( float ) ) ;
2013-10-18 09:55:43 +04:00
float mtx [ 16 ] ;
2014-05-27 06:31:37 +04:00
bx : : mtxSRT ( mtx
2013-10-20 22:34:28 +04:00
, m_scale [ 0 ]
, m_scale [ 1 ]
, m_scale [ 2 ]
, m_rotation [ 0 ]
, m_rotation [ 1 ]
, m_rotation [ 2 ]
, m_pos [ 0 ]
, m_pos [ 1 ]
, m_pos [ 2 ]
) ;
2013-10-18 09:55:43 +04:00
BX_CHECK ( NULL ! = m_model , " Instance model cannot be NULL! " ) ;
m_model - > submit ( _viewId , mtx , _renderState ) ;
}
float m_scale [ 3 ] ;
float m_rotation [ 3 ] ;
float m_pos [ 3 ] ;
float m_color [ 3 ] ;
float m_svExtrusionDistance ;
Model * m_model ;
} ;
2013-11-09 22:06:06 +04:00
# define SV_INSTANCE_MEM_SIZE (1500 << 10)
# define SV_INSTANCE_COUNT ( (25 > MAX_INSTANCE_COUNT) ? 25 : MAX_INSTANCE_COUNT)
# define SV_PAGE_SIZE (SV_INSTANCE_MEM_SIZE * SV_INSTANCE_COUNT * MAX_LIGHTS_COUNT)
2013-10-24 04:02:10 +04:00
struct ShadowVolumeAllocator
{
ShadowVolumeAllocator ( )
{
2013-11-09 22:06:06 +04:00
m_mem = ( uint8_t * ) malloc ( SV_PAGE_SIZE * 2 ) ;
2013-10-24 04:02:10 +04:00
m_ptr = m_mem ;
m_firstPage = true ;
}
~ ShadowVolumeAllocator ( )
{
free ( m_mem ) ;
}
void * alloc ( uint32_t _size )
{
void * ret = ( void * ) m_ptr ;
m_ptr + = _size ;
2013-11-09 22:06:06 +04:00
BX_CHECK ( m_ptr - m_mem < ( m_firstPage ? SV_PAGE_SIZE : 2 * SV_PAGE_SIZE ) , " Buffer overflow! " ) ;
2013-10-24 04:02:10 +04:00
return ret ;
}
void swap ( )
{
2013-11-09 22:06:06 +04:00
m_ptr = m_firstPage ? m_mem + SV_PAGE_SIZE : m_mem ;
2013-10-24 04:02:10 +04:00
m_firstPage = ! m_firstPage ;
}
uint8_t * m_mem ;
uint8_t * m_ptr ;
bool m_firstPage ;
} ;
static ShadowVolumeAllocator s_svAllocator ;
2013-10-18 09:55:43 +04:00
struct ShadowVolumeImpl
{
enum Enum
{
DepthPass ,
DepthFail ,
} ;
} ;
struct ShadowVolumeAlgorithm
{
enum Enum
{
FaceBased ,
EdgeBased ,
} ;
} ;
struct ShadowVolume
{
bgfx : : VertexBufferHandle m_vbSides ;
bgfx : : IndexBufferHandle m_ibSides ;
bgfx : : IndexBufferHandle m_ibFrontCap ;
bgfx : : IndexBufferHandle m_ibBackCap ;
2013-10-20 22:34:28 +04:00
2013-10-18 09:55:43 +04:00
uint32_t m_numVertices ;
uint32_t m_numIndices ;
const float * m_mtx ;
const float * m_lightPos ;
bool m_cap ;
} ;
2013-10-30 09:44:41 +04:00
void shadowVolumeLightTransform ( float * __restrict _outLightPos
, const float * __restrict _scale
, const float * __restrict _rotate
, const float * __restrict _translate
, const float * __restrict _lightPos // world pos
)
2013-10-18 09:55:43 +04:00
{
2013-10-21 00:11:41 +04:00
/**
2013-10-18 09:55:43 +04:00
* Instead of transforming all the vertices , transform light instead :
* mtx = pivotTranslate - > rotateZYX - > invScale
* light = mtx * origin
*/
2013-10-20 22:34:28 +04:00
float pivot [ 16 ] ;
2014-05-27 06:31:37 +04:00
bx : : mtxTranslate ( pivot
2013-10-20 22:34:28 +04:00
, _lightPos [ 0 ] - _translate [ 0 ]
, _lightPos [ 1 ] - _translate [ 1 ]
, _lightPos [ 2 ] - _translate [ 2 ]
) ;
float mzyx [ 16 ] ;
2014-05-27 06:31:37 +04:00
bx : : mtxRotateZYX ( mzyx
2013-10-20 22:34:28 +04:00
, - _rotate [ 0 ]
, - _rotate [ 1 ]
, - _rotate [ 2 ]
) ;
float invScale [ 16 ] ;
2014-05-27 06:31:37 +04:00
bx : : mtxScale ( invScale
2013-10-20 22:34:28 +04:00
, 1.0f / _scale [ 0 ]
, 1.0f / _scale [ 1 ]
, 1.0f / _scale [ 2 ]
) ;
float tmp0 [ 16 ] ;
2014-05-27 06:31:37 +04:00
bx : : mtxMul ( tmp0 , pivot , mzyx ) ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
float mtx [ 16 ] ;
2014-05-27 06:31:37 +04:00
bx : : mtxMul ( mtx , tmp0 , invScale ) ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
float origin [ 3 ] = { 0.0f , 0.0f , 0.0f } ;
2014-05-27 06:31:37 +04:00
bx : : vec3MulMtx ( _outLightPos , origin , mtx ) ;
2013-10-18 09:55:43 +04:00
}
void shadowVolumeCreate ( ShadowVolume & _shadowVolume
2013-10-20 22:34:28 +04:00
, Group & _group
, uint16_t _stride
, const float * _mtx
, const float * _light // in model space
, ShadowVolumeImpl : : Enum _impl = ShadowVolumeImpl : : DepthPass
, ShadowVolumeAlgorithm : : Enum _algo = ShadowVolumeAlgorithm : : FaceBased
, bool _textureAsStencil = false
)
2013-10-18 09:55:43 +04:00
{
2013-11-13 20:53:44 +04:00
const uint8_t * vertices = _group . m_vertices ;
const FaceArray & faces = _group . m_faces ;
const Edge * edges = _group . m_edges ;
const Plane * edgePlanes = _group . m_edgePlanes ;
const uint32_t numEdges = _group . m_numEdges ;
HalfEdges & halfEdges = _group . m_halfEdges ;
2013-10-18 09:55:43 +04:00
struct VertexData
{
2013-10-20 22:34:28 +04:00
VertexData ( )
{
}
2013-10-18 09:55:43 +04:00
VertexData ( const float * _v3 , float _extrude = 0.0f , float _k = 1.0f )
{
2017-02-09 06:55:31 +03:00
bx : : memCopy ( m_v , _v3 , 3 * sizeof ( float ) ) ;
2013-10-18 09:55:43 +04:00
m_extrude = _extrude ;
m_k = _k ;
}
float m_v [ 3 ] ;
2013-10-20 22:34:28 +04:00
float m_extrude ;
float m_k ;
2013-10-18 09:55:43 +04:00
} ;
2013-10-25 00:56:13 +04:00
bool cap = ( ShadowVolumeImpl : : DepthFail = = _impl ) ;
2013-11-13 01:20:50 +04:00
VertexData * verticesSide = ( VertexData * ) s_svAllocator . alloc ( 20000 * sizeof ( VertexData ) ) ;
uint16_t * indicesSide = ( uint16_t * ) s_svAllocator . alloc ( 20000 * 3 * sizeof ( uint16_t ) ) ;
2013-10-25 00:56:13 +04:00
uint16_t * indicesFrontCap = 0 ;
uint16_t * indicesBackCap = 0 ;
if ( cap )
{
indicesFrontCap = ( uint16_t * ) s_svAllocator . alloc ( 80000 * 3 * sizeof ( uint16_t ) ) ;
indicesBackCap = ( uint16_t * ) s_svAllocator . alloc ( 80000 * 3 * sizeof ( uint16_t ) ) ;
}
2013-10-18 09:55:43 +04:00
2013-10-22 00:32:42 +04:00
uint32_t vsideI = 0 ;
uint32_t sideI = 0 ;
uint32_t frontCapI = 0 ;
uint32_t backCapI = 0 ;
2013-10-18 09:55:43 +04:00
uint16_t indexSide = 0 ;
2013-10-20 22:34:28 +04:00
if ( ShadowVolumeAlgorithm : : FaceBased = = _algo )
2013-10-18 09:55:43 +04:00
{
2013-10-20 22:34:28 +04:00
for ( FaceArray : : const_iterator iter = faces . begin ( ) , end = faces . end ( ) ; iter ! = end ; + + iter )
{
const Face & face = * iter ;
bool frontFacing = false ;
2014-05-27 06:31:37 +04:00
float f = bx : : vec3Dot ( face . m_plane , _light ) + face . m_plane [ 3 ] ;
2013-10-20 22:34:28 +04:00
if ( f > 0.0f )
2013-10-18 09:55:43 +04:00
{
2013-10-20 22:34:28 +04:00
frontFacing = true ;
2013-11-13 01:20:50 +04:00
uint16_t triangleEdges [ 3 ] [ 2 ] =
2013-10-18 09:55:43 +04:00
{
2013-10-22 00:32:42 +04:00
{ face . m_i [ 0 ] , face . m_i [ 1 ] } ,
{ face . m_i [ 1 ] , face . m_i [ 2 ] } ,
{ face . m_i [ 2 ] , face . m_i [ 0 ] } ,
2013-10-20 22:34:28 +04:00
} ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
for ( uint8_t ii = 0 ; ii < 3 ; + + ii )
{
uint16_t first = triangleEdges [ ii ] [ 0 ] ;
uint16_t second = triangleEdges [ ii ] [ 1 ] ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
if ( ! halfEdges . unmark ( second , first ) )
2013-10-18 09:55:43 +04:00
{
2013-10-20 22:34:28 +04:00
halfEdges . mark ( first , second ) ;
2013-10-18 09:55:43 +04:00
}
}
2013-10-20 22:34:28 +04:00
}
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
if ( cap )
{
if ( frontFacing )
2013-10-18 09:55:43 +04:00
{
2013-10-22 00:32:42 +04:00
indicesFrontCap [ frontCapI + + ] = face . m_i [ 0 ] ;
indicesFrontCap [ frontCapI + + ] = face . m_i [ 1 ] ;
indicesFrontCap [ frontCapI + + ] = face . m_i [ 2 ] ;
2013-10-20 22:34:28 +04:00
}
else
{
2013-10-22 00:32:42 +04:00
indicesBackCap [ backCapI + + ] = face . m_i [ 0 ] ;
indicesBackCap [ backCapI + + ] = face . m_i [ 1 ] ;
indicesBackCap [ backCapI + + ] = face . m_i [ 2 ] ;
2013-10-20 22:34:28 +04:00
}
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
/**
* if ' _useFrontFacingFacesAsBackCap ' is needed , implement it as such :
*
* bool condition0 = frontFacing & & _useFrontFacingFacesAsBackCap ;
* bool condition1 = ! frontFacing & & ! _useFrontFacingFacesAsBackCap ;
* if ( condition0 | | condition1 )
* {
2013-10-22 00:32:42 +04:00
* indicesBackCap [ backCapI + + ] = face . m_i [ 0 ] ;
* indicesBackCap [ backCapI + + ] = face . m_i [ 1 + condition0 ] ;
* indicesBackCap [ backCapI + + ] = face . m_i [ 2 - condition0 ] ;
2013-10-20 22:34:28 +04:00
* }
*/
}
}
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
// Fill side arrays.
uint16_t firstIndex = 0 ;
HalfEdge * he = halfEdges . begin ( ) ;
while ( halfEdges . end ( ) ! = he )
{
if ( he - > m_marked )
{
he - > m_marked = false ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
const float * v0 = ( float * ) & vertices [ firstIndex * _stride ] ;
const float * v1 = ( float * ) & vertices [ he - > m_secondIndex * _stride ] ;
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
verticesSide [ vsideI + + ] = VertexData ( v0 , 0.0f ) ;
verticesSide [ vsideI + + ] = VertexData ( v0 , 1.0f ) ;
verticesSide [ vsideI + + ] = VertexData ( v1 , 0.0f ) ;
verticesSide [ vsideI + + ] = VertexData ( v1 , 1.0f ) ;
2013-10-18 09:55:43 +04:00
2013-10-22 00:32:42 +04:00
indicesSide [ sideI + + ] = indexSide + 0 ;
indicesSide [ sideI + + ] = indexSide + 1 ;
indicesSide [ sideI + + ] = indexSide + 2 ;
indicesSide [ sideI + + ] = indexSide + 2 ;
indicesSide [ sideI + + ] = indexSide + 1 ;
indicesSide [ sideI + + ] = indexSide + 3 ;
2013-10-20 22:34:28 +04:00
indexSide + = 4 ;
2013-10-18 09:55:43 +04:00
}
2013-10-20 22:34:28 +04:00
+ + he ;
if ( INVALID_EDGE_INDEX = = he - > m_secondIndex )
{
+ + he ;
+ + firstIndex ;
}
}
}
else // ShadowVolumeAlgorithm::EdgeBased:
{
2015-04-05 02:40:28 +03:00
{
uint32_t ii = 0 ;
2013-10-20 22:34:28 +04:00
2013-11-13 01:18:14 +04:00
# if SV_USE_SIMD
2015-04-05 02:40:28 +03:00
uint32_t numEdgesRounded = numEdges & ( ~ 0x1 ) ;
2013-11-13 01:18:14 +04:00
2015-04-05 02:40:28 +03:00
using namespace bx ;
2013-11-03 14:16:51 +04:00
2016-07-19 05:03:25 +03:00
const simd128_t lx = simd_splat ( _light [ 0 ] ) ;
const simd128_t ly = simd_splat ( _light [ 1 ] ) ;
const simd128_t lz = simd_splat ( _light [ 2 ] ) ;
2013-11-13 01:18:14 +04:00
2015-04-05 02:40:28 +03:00
for ( ; ii < numEdgesRounded ; ii + = 2 )
2013-11-13 01:18:14 +04:00
{
2015-04-05 02:40:28 +03:00
const Edge & edge0 = edges [ ii ] ;
const Edge & edge1 = edges [ ii + 1 ] ;
const Plane * edgePlane0 = & edgePlanes [ ii * 2 ] ;
const Plane * edgePlane1 = & edgePlanes [ ii * 2 + 2 ] ;
2016-07-19 05:03:25 +03:00
const simd128_t reverse =
simd_ild ( edge0 . m_faceReverseOrder [ 0 ]
2015-04-05 02:40:28 +03:00
, edge1 . m_faceReverseOrder [ 0 ]
, edge0 . m_faceReverseOrder [ 1 ]
, edge1 . m_faceReverseOrder [ 1 ]
) ;
2016-07-19 05:03:25 +03:00
const simd128_t p00 = simd_ld ( edgePlane0 [ 0 ] . m_plane ) ;
const simd128_t p10 = simd_ld ( edgePlane1 [ 0 ] . m_plane ) ;
const simd128_t p01 = simd_ld ( edgePlane0 [ 1 ] . m_plane ) ;
const simd128_t p11 = simd_ld ( edgePlane1 [ 1 ] . m_plane ) ;
const simd128_t xxyy0 = simd_shuf_xAyB ( p00 , p01 ) ;
const simd128_t zzww0 = simd_shuf_zCwD ( p00 , p01 ) ;
const simd128_t xxyy1 = simd_shuf_xAyB ( p10 , p11 ) ;
const simd128_t zzww1 = simd_shuf_zCwD ( p10 , p11 ) ;
const simd128_t vX = simd_shuf_xAyB ( xxyy0 , xxyy1 ) ;
const simd128_t vY = simd_shuf_zCwD ( xxyy0 , xxyy1 ) ;
const simd128_t vZ = simd_shuf_xAyB ( zzww0 , zzww1 ) ;
const simd128_t vW = simd_shuf_zCwD ( zzww0 , zzww1 ) ;
const simd128_t r0 = simd_mul ( vX , lx ) ;
const simd128_t r1 = simd_mul ( vY , ly ) ;
const simd128_t r2 = simd_mul ( vZ , lz ) ;
const simd128_t dot = simd_add ( r0 , simd_add ( r1 , r2 ) ) ;
const simd128_t f = simd_add ( dot , vW ) ;
const simd128_t zero = simd_zero ( ) ;
const simd128_t mask = simd_cmpgt ( f , zero ) ;
const simd128_t onef = simd_splat ( 1.0f ) ;
const simd128_t tmp0 = simd_and ( mask , onef ) ;
const simd128_t tmp1 = simd_ftoi ( tmp0 ) ;
const simd128_t tmp2 = simd_xor ( tmp1 , reverse ) ;
const simd128_t tmp3 = simd_sll ( tmp2 , 1 ) ;
const simd128_t onei = simd_isplat ( 1 ) ;
const simd128_t tmp4 = simd_isub ( tmp3 , onei ) ;
2015-04-05 02:40:28 +03:00
BX_ALIGN_DECL_16 ( int32_t res [ 4 ] ) ;
2016-07-19 05:03:25 +03:00
simd_st ( & res , tmp4 ) ;
2015-04-05 02:40:28 +03:00
for ( uint16_t jj = 0 ; jj < 2 ; + + jj )
2013-10-18 09:55:43 +04:00
{
2017-03-13 04:25:23 +03:00
int32_t kk = res [ jj ] + res [ jj + 2 ] ;
2015-04-05 02:40:28 +03:00
if ( kk ! = 0 )
2013-11-13 01:18:14 +04:00
{
2015-04-05 02:40:28 +03:00
float * v0 = ( float * ) & vertices [ edges [ ii + jj ] . m_i0 * _stride ] ;
float * v1 = ( float * ) & vertices [ edges [ ii + jj ] . m_i1 * _stride ] ;
verticesSide [ vsideI + + ] = VertexData ( v0 , 0.0f , float ( kk ) ) ;
verticesSide [ vsideI + + ] = VertexData ( v0 , 1.0f , float ( kk ) ) ;
verticesSide [ vsideI + + ] = VertexData ( v1 , 0.0f , float ( kk ) ) ;
verticesSide [ vsideI + + ] = VertexData ( v1 , 1.0f , float ( kk ) ) ;
kk = _textureAsStencil ? 1 : kk ;
uint16_t winding = uint16_t ( kk > 0 ) ;
2017-03-13 04:25:23 +03:00
for ( int32_t ll = 0 , end = abs ( kk ) ; ll < end ; + + ll )
2015-04-05 02:40:28 +03:00
{
indicesSide [ sideI + + ] = indexSide ;
indicesSide [ sideI + + ] = indexSide + 2 - winding ;
indicesSide [ sideI + + ] = indexSide + 1 + winding ;
2013-11-13 01:18:14 +04:00
2015-04-05 02:40:28 +03:00
indicesSide [ sideI + + ] = indexSide + 2 ;
indicesSide [ sideI + + ] = indexSide + 3 - winding * 2 ;
indicesSide [ sideI + + ] = indexSide + 1 + winding * 2 ;
}
2013-11-13 01:18:14 +04:00
2015-04-05 02:40:28 +03:00
indexSide + = 4 ;
}
2013-10-20 22:34:28 +04:00
}
}
2013-11-13 01:18:14 +04:00
# endif
2013-10-18 09:55:43 +04:00
2015-04-05 02:40:28 +03:00
for ( ; ii < numEdges ; + + ii )
{
const Edge & edge = edges [ ii ] ;
const Plane * edgePlane = & edgePlanes [ ii * 2 ] ;
2013-10-18 09:55:43 +04:00
2015-04-05 02:40:28 +03:00
int16_t s0 = ( ( vec3Dot ( edgePlane [ 0 ] . m_plane , _light ) + edgePlane [ 0 ] . m_plane [ 3 ] ) > 0.0f ) ^ edge . m_faceReverseOrder [ 0 ] ;
int16_t s1 = ( ( vec3Dot ( edgePlane [ 1 ] . m_plane , _light ) + edgePlane [ 1 ] . m_plane [ 3 ] ) > 0.0f ) ^ edge . m_faceReverseOrder [ 1 ] ;
int16_t kk = ( ( s0 + s1 ) < < 1 ) - 2 ;
2013-10-18 09:55:43 +04:00
2015-04-05 02:40:28 +03:00
if ( kk ! = 0 )
2013-11-13 01:18:14 +04:00
{
2015-04-05 02:40:28 +03:00
float * v0 = ( float * ) & vertices [ edge . m_i0 * _stride ] ;
float * v1 = ( float * ) & vertices [ edge . m_i1 * _stride ] ;
verticesSide [ vsideI + + ] = VertexData ( v0 , 0.0f , kk ) ;
verticesSide [ vsideI + + ] = VertexData ( v0 , 1.0f , kk ) ;
verticesSide [ vsideI + + ] = VertexData ( v1 , 0.0f , kk ) ;
verticesSide [ vsideI + + ] = VertexData ( v1 , 1.0f , kk ) ;
kk = _textureAsStencil ? 1 : kk ;
uint16_t winding = uint16_t ( kk > 0 ) ;
2017-03-13 04:25:23 +03:00
for ( int32_t jj = 0 , end = abs ( kk ) ; jj < end ; + + jj )
2015-04-05 02:40:28 +03:00
{
indicesSide [ sideI + + ] = indexSide ;
indicesSide [ sideI + + ] = indexSide + 2 - winding ;
indicesSide [ sideI + + ] = indexSide + 1 + winding ;
2013-10-22 00:32:42 +04:00
2015-04-05 02:40:28 +03:00
indicesSide [ sideI + + ] = indexSide + 2 ;
indicesSide [ sideI + + ] = indexSide + 3 - winding * 2 ;
indicesSide [ sideI + + ] = indexSide + 1 + winding * 2 ;
}
2013-10-18 09:55:43 +04:00
2015-04-05 02:40:28 +03:00
indexSide + = 4 ;
}
2013-11-13 01:18:14 +04:00
}
2013-10-20 22:34:28 +04:00
}
2013-10-18 09:55:43 +04:00
2013-10-20 22:34:28 +04:00
if ( cap )
{
// This could/should be done on GPU!
for ( FaceArray : : const_iterator iter = faces . begin ( ) , end = faces . end ( ) ; iter ! = end ; + + iter )
{
const Face & face = * iter ;
2013-10-18 09:55:43 +04:00
2015-04-05 02:40:28 +03:00
float f = bx : : vec3Dot ( face . m_plane , _light ) + face . m_plane [ 3 ] ;
2013-11-13 01:20:50 +04:00
bool frontFacing = ( f > 0.0f ) ;
2013-10-18 09:55:43 +04:00
2015-04-05 02:40:28 +03:00
for ( uint8_t ii = 0 , num = 1 + uint8_t ( ! _textureAsStencil ) ; ii < num ; + + ii )
2013-10-20 22:34:28 +04:00
{
if ( frontFacing )
{
2013-10-22 00:32:42 +04:00
indicesFrontCap [ frontCapI + + ] = face . m_i [ 0 ] ;
indicesFrontCap [ frontCapI + + ] = face . m_i [ 1 ] ;
indicesFrontCap [ frontCapI + + ] = face . m_i [ 2 ] ;
2013-10-20 22:34:28 +04:00
}
else
{
2013-10-22 00:32:42 +04:00
indicesBackCap [ backCapI + + ] = face . m_i [ 0 ] ;
indicesBackCap [ backCapI + + ] = face . m_i [ 1 ] ;
indicesBackCap [ backCapI + + ] = face . m_i [ 2 ] ;
2013-10-18 09:55:43 +04:00
}
}
}
2013-10-20 22:34:28 +04:00
}
2013-10-18 09:55:43 +04:00
}
bgfx : : VertexDecl decl ;
2014-05-11 07:51:44 +04:00
decl . begin ( )
. add ( bgfx : : Attrib : : Position , 3 , bgfx : : AttribType : : Float )
. add ( bgfx : : Attrib : : TexCoord0 , 2 , bgfx : : AttribType : : Float )
. end ( ) ;
2013-10-18 09:55:43 +04:00
//fill the structure
_shadowVolume . m_numVertices = vsideI ;
_shadowVolume . m_numIndices = sideI + frontCapI + backCapI ;
_shadowVolume . m_mtx = _mtx ;
_shadowVolume . m_lightPos = _light ;
_shadowVolume . m_cap = cap ;
const bgfx : : Memory * mem ;
//sides
uint32_t vsize = vsideI * 5 * sizeof ( float ) ;
2013-10-22 00:32:42 +04:00
uint32_t isize = sideI * sizeof ( uint16_t ) ;
2013-10-18 09:55:43 +04:00
2013-10-24 04:02:10 +04:00
mem = bgfx : : makeRef ( verticesSide , vsize ) ;
2013-10-18 09:55:43 +04:00
_shadowVolume . m_vbSides = bgfx : : createVertexBuffer ( mem , decl ) ;
2013-10-24 04:02:10 +04:00
mem = bgfx : : makeRef ( indicesSide , isize ) ;
2013-10-18 09:55:43 +04:00
_shadowVolume . m_ibSides = bgfx : : createIndexBuffer ( mem ) ;
// bgfx::destroy*Buffer doesn't actually destroy buffers now.
// Instead, these bgfx::destroy*Buffer commands get queued to be executed after the end of the next frame.
bgfx : : destroyVertexBuffer ( _shadowVolume . m_vbSides ) ;
bgfx : : destroyIndexBuffer ( _shadowVolume . m_ibSides ) ;
if ( cap )
{
//front cap
2013-10-22 00:32:42 +04:00
isize = frontCapI * sizeof ( uint16_t ) ;
2013-10-24 04:02:10 +04:00
mem = bgfx : : makeRef ( indicesFrontCap , isize ) ;
2013-10-18 09:55:43 +04:00
_shadowVolume . m_ibFrontCap = bgfx : : createIndexBuffer ( mem ) ;
//gets destroyed after the end of the next frame
bgfx : : destroyIndexBuffer ( _shadowVolume . m_ibFrontCap ) ;
//back cap
2013-10-22 00:32:42 +04:00
isize = backCapI * sizeof ( uint16_t ) ;
2013-10-24 04:02:10 +04:00
mem = bgfx : : makeRef ( indicesBackCap , isize ) ;
2013-10-18 09:55:43 +04:00
_shadowVolume . m_ibBackCap = bgfx : : createIndexBuffer ( mem ) ;
//gets destroyed after the end of the next frame
bgfx : : destroyIndexBuffer ( _shadowVolume . m_ibBackCap ) ;
}
}
void createNearClipVolume ( float * __restrict _outPlanes24f
2013-10-20 22:34:28 +04:00
, float * __restrict _lightPos
, float * __restrict _view
, float _fovy
, float _aspect
, float _near
)
2013-10-18 09:55:43 +04:00
{
float ( * volumePlanes ) [ 4 ] = ( float ( * ) [ 4 ] ) _outPlanes24f ;
float mtxViewInv [ 16 ] ;
float mtxViewTrans [ 16 ] ;
2014-05-27 06:31:37 +04:00
bx : : mtxInverse ( mtxViewInv , _view ) ;
bx : : mtxTranspose ( mtxViewTrans , _view ) ;
2013-10-18 09:55:43 +04:00
float lightPosV [ 4 ] ;
2014-05-27 06:31:37 +04:00
bx : : vec4MulMtx ( lightPosV , _lightPos , _view ) ;
2013-10-18 09:55:43 +04:00
const float delta = 0.1f ;
float nearNormal [ 4 ] = { 0.0f , 0.0f , 1.0f , _near } ;
2014-05-27 06:31:37 +04:00
float d = bx : : vec3Dot ( lightPosV , nearNormal ) + lightPosV [ 3 ] * nearNormal [ 3 ] ;
2013-10-18 09:55:43 +04:00
// Light is:
// 1.0f - in front of near plane
// 0.0f - on the near plane
// -1.0f - behind near plane
2013-10-20 22:34:28 +04:00
float lightSide = float ( ( d > delta ) - ( d < - delta ) ) ;
2013-10-18 09:55:43 +04:00
2017-02-15 07:27:31 +03:00
float t = bx : : ftan ( bx : : toRad ( _fovy ) * 0.5f ) * _near ;
2013-10-18 09:55:43 +04:00
float b = - t ;
float r = t * _aspect ;
float l = - r ;
float cornersV [ 4 ] [ 3 ] =
{
{ r , t , _near } ,
{ l , t , _near } ,
{ l , b , _near } ,
{ r , b , _near } ,
} ;
float corners [ 4 ] [ 3 ] ;
2014-05-27 06:31:37 +04:00
bx : : vec3MulMtx ( corners [ 0 ] , cornersV [ 0 ] , mtxViewInv ) ;
bx : : vec3MulMtx ( corners [ 1 ] , cornersV [ 1 ] , mtxViewInv ) ;
bx : : vec3MulMtx ( corners [ 2 ] , cornersV [ 2 ] , mtxViewInv ) ;
bx : : vec3MulMtx ( corners [ 3 ] , cornersV [ 3 ] , mtxViewInv ) ;
2013-10-18 09:55:43 +04:00
float planeNormals [ 4 ] [ 3 ] ;
for ( uint8_t ii = 0 ; ii < 4 ; + + ii )
{
float * normal = planeNormals [ ii ] ;
float * plane = volumePlanes [ ii ] ;
float planeVec [ 3 ] ;
2014-05-27 06:31:37 +04:00
bx : : vec3Sub ( planeVec , corners [ ii ] , corners [ ( ii - 1 ) % 4 ] ) ;
2013-10-18 09:55:43 +04:00
float light [ 3 ] ;
float tmp [ 3 ] ;
2014-05-27 06:31:37 +04:00
bx : : vec3Mul ( tmp , corners [ ii ] , _lightPos [ 3 ] ) ;
bx : : vec3Sub ( light , _lightPos , tmp ) ;
2013-10-18 09:55:43 +04:00
2014-05-27 06:31:37 +04:00
bx : : vec3Cross ( normal , planeVec , light ) ;
2013-10-20 22:34:28 +04:00
2013-10-18 09:55:43 +04:00
normal [ 0 ] * = lightSide ;
normal [ 1 ] * = lightSide ;
normal [ 2 ] * = lightSide ;
2017-02-15 07:27:31 +03:00
float lenInv = 1.0f / bx : : fsqrt ( bx : : vec3Dot ( normal , normal ) ) ;
2013-10-18 09:55:43 +04:00
plane [ 0 ] = normal [ 0 ] * lenInv ;
plane [ 1 ] = normal [ 1 ] * lenInv ;
plane [ 2 ] = normal [ 2 ] * lenInv ;
2014-05-27 06:31:37 +04:00
plane [ 3 ] = - bx : : vec3Dot ( normal , corners [ ii ] ) * lenInv ;
2013-10-18 09:55:43 +04:00
}
float nearPlaneV [ 4 ] =
{
2013-11-13 01:20:50 +04:00
0.0f * lightSide ,
0.0f * lightSide ,
1.0f * lightSide ,
_near * lightSide ,
2013-10-18 09:55:43 +04:00
} ;
2014-05-27 06:31:37 +04:00
bx : : vec4MulMtx ( volumePlanes [ 4 ] , nearPlaneV , mtxViewTrans ) ;
2013-10-18 09:55:43 +04:00
float * lightPlane = volumePlanes [ 5 ] ;
float lightPlaneNormal [ 3 ] = { 0.0f , 0.0f , - _near * lightSide } ;
float tmp [ 3 ] ;
2014-05-27 06:31:37 +04:00
bx : : vec3MulMtx ( tmp , lightPlaneNormal , mtxViewInv ) ;
bx : : vec3Sub ( lightPlaneNormal , tmp , _lightPos ) ;
2013-10-18 09:55:43 +04:00
2017-02-15 07:27:31 +03:00
float lenInv = 1.0f / bx : : fsqrt ( bx : : vec3Dot ( lightPlaneNormal , lightPlaneNormal ) ) ;
2013-10-18 09:55:43 +04:00
lightPlane [ 0 ] = lightPlaneNormal [ 0 ] * lenInv ;
lightPlane [ 1 ] = lightPlaneNormal [ 1 ] * lenInv ;
lightPlane [ 2 ] = lightPlaneNormal [ 2 ] * lenInv ;
2014-05-27 06:31:37 +04:00
lightPlane [ 3 ] = - bx : : vec3Dot ( lightPlaneNormal , _lightPos ) * lenInv ;
2013-10-18 09:55:43 +04:00
}
bool clipTest ( const float * _planes , uint8_t _planeNum , const Mesh & _mesh , const float * _scale , const float * _translate )
{
float ( * volumePlanes ) [ 4 ] = ( float ( * ) [ 4 ] ) _planes ;
2014-05-27 06:31:37 +04:00
float scale = bx : : fmax ( bx : : fmax ( _scale [ 0 ] , _scale [ 1 ] ) , _scale [ 2 ] ) ;
2013-10-18 09:55:43 +04:00
const GroupArray & groups = _mesh . m_groups ;
for ( GroupArray : : const_iterator it = groups . begin ( ) , itEnd = groups . end ( ) ; it ! = itEnd ; + + it )
{
const Group & group = * it ;
Sphere sphere = group . m_sphere ;
sphere . m_center [ 0 ] = sphere . m_center [ 0 ] * scale + _translate [ 0 ] ;
sphere . m_center [ 1 ] = sphere . m_center [ 1 ] * scale + _translate [ 1 ] ;
sphere . m_center [ 2 ] = sphere . m_center [ 2 ] * scale + _translate [ 2 ] ;
sphere . m_radius * = ( scale + 0.4f ) ;
bool isInside = true ;
for ( uint8_t ii = 0 ; ii < _planeNum ; + + ii )
{
const float * plane = volumePlanes [ ii ] ;
2014-05-27 06:31:37 +04:00
float positiveSide = bx : : vec3Dot ( plane , sphere . m_center ) + plane [ 3 ] + sphere . m_radius ;
2013-10-18 09:55:43 +04:00
if ( positiveSide < 0.0f )
{
isInside = false ;
break ;
}
}
2013-11-13 01:20:50 +04:00
if ( isInside )
2013-10-18 09:55:43 +04:00
{
2013-11-13 01:20:50 +04:00
return true ;
2013-10-18 09:55:43 +04:00
}
}
return false ;
}
2017-06-15 19:57:08 +03:00
struct ShadowVolumeProgramType
2013-10-18 09:55:43 +04:00
{
2017-06-15 19:57:08 +03:00
enum Enum
2013-10-20 22:34:28 +04:00
{
2017-06-15 19:57:08 +03:00
Blank = 0 ,
Color ,
Tex1 ,
Tex2 ,
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
Count
2013-10-20 22:34:28 +04:00
} ;
2017-06-15 19:57:08 +03:00
} ;
2013-10-20 22:34:28 +04:00
2017-06-15 19:57:08 +03:00
struct ShadowVolumePart
{
enum Enum
2013-10-20 22:34:28 +04:00
{
2017-06-15 19:57:08 +03:00
Back = 0 ,
Side ,
Front ,
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
Count
2013-10-20 22:34:28 +04:00
} ;
2017-06-15 19:57:08 +03:00
} ;
2013-10-20 22:34:28 +04:00
2017-06-15 19:57:08 +03:00
enum LightPattern
{
LightPattern0 = 0 ,
LightPattern1
} ;
2013-10-20 22:34:28 +04:00
2017-06-15 19:57:08 +03:00
enum MeshChoice
{
BunnyHighPoly = 0 ,
BunnyLowPoly
} ;
2014-01-30 21:20:06 +04:00
2017-06-15 19:57:08 +03:00
enum Scene
{
Scene0 = 0 ,
Scene1 ,
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
SceneCount
} ;
2014-01-30 21:20:06 +04:00
2017-06-15 19:57:08 +03:00
class ExampleShadowVolumes : public entry : : AppI
{
void init ( int _argc , char * * _argv ) BX_OVERRIDE
2013-10-18 09:55:43 +04:00
{
2017-06-15 19:57:08 +03:00
Args args ( _argc , _argv ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_viewState = ViewState ( 1280 , 720 ) ;
2017-06-21 06:56:13 +03:00
m_clearValues = { 0x00000000 , 1.0f , 0 } ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_debug = BGFX_DEBUG_TEXT ;
m_reset = BGFX_RESET_VSYNC ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : init ( args . m_type , args . m_pciId ) ;
bgfx : : reset ( m_viewState . m_width , m_viewState . m_height , m_reset ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Enable debug text.
bgfx : : setDebug ( m_debug ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
const bgfx : : Caps * caps = bgfx : : getCaps ( ) ;
s_oglNdc = caps - > homogeneousDepth ;
s_texelHalf = bgfx : : RendererType : : Direct3D9 = = caps - > rendererType ? 0.5f : 0.0f ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Imgui
imguiCreate ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
PosNormalTexcoordVertex : : init ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
s_uniforms . init ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_figureTex = loadTexture ( " textures/figure-rgba.dds " ) ;
m_flareTex = loadTexture ( " textures/flare.dds " ) ;
m_fieldstoneTex = loadTexture ( " textures/fieldstone-rgba.dds " ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : TextureHandle fbtextures [ ] =
2014-11-02 10:06:18 +03:00
{
2017-06-15 19:57:08 +03:00
bgfx : : createTexture2D ( uint16_t ( m_viewState . m_width ) , uint16_t ( m_viewState . m_height ) , false , 1 , bgfx : : TextureFormat : : BGRA8 , BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | BGFX_TEXTURE_RT ) ,
2017-06-21 06:56:13 +03:00
bgfx : : createTexture2D ( uint16_t ( m_viewState . m_width ) , uint16_t ( m_viewState . m_height ) , false , 1 , bgfx : : TextureFormat : : D16 , BGFX_TEXTURE_RT_WRITE_ONLY ) ,
2017-06-15 19:57:08 +03:00
} ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
s_stencilFb = bgfx : : createFrameBuffer ( BX_COUNTOF ( fbtextures ) , fbtextures , true ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
s_texColor = bgfx : : createUniform ( " s_texColor " , bgfx : : UniformType : : Int1 ) ;
s_texStencil = bgfx : : createUniform ( " s_texStencil " , bgfx : : UniformType : : Int1 ) ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:56:13 +03:00
m_programTextureLighting = loadProgram ( " vs_shadowvolume_texture_lighting " , " fs_shadowvolume_texture_lighting " ) ;
m_programColorLighting = loadProgram ( " vs_shadowvolume_color_lighting " , " fs_shadowvolume_color_lighting " ) ;
m_programColorTexture = loadProgram ( " vs_shadowvolume_color_texture " , " fs_shadowvolume_color_texture " ) ;
m_programTexture = loadProgram ( " vs_shadowvolume_texture " , " fs_shadowvolume_texture " ) ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:56:13 +03:00
m_programBackBlank = loadProgram ( " vs_shadowvolume_svback " , " fs_shadowvolume_svbackblank " ) ;
m_programSideBlank = loadProgram ( " vs_shadowvolume_svside " , " fs_shadowvolume_svsideblank " ) ;
m_programFrontBlank = loadProgram ( " vs_shadowvolume_svfront " , " fs_shadowvolume_svfrontblank " ) ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:56:13 +03:00
m_programBackColor = loadProgram ( " vs_shadowvolume_svback " , " fs_shadowvolume_svbackcolor " ) ;
m_programSideColor = loadProgram ( " vs_shadowvolume_svside " , " fs_shadowvolume_svsidecolor " ) ;
m_programFrontColor = loadProgram ( " vs_shadowvolume_svfront " , " fs_shadowvolume_svfrontcolor " ) ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:56:13 +03:00
m_programSideTex = loadProgram ( " vs_shadowvolume_svside " , " fs_shadowvolume_svsidetex " ) ;
m_programBackTex1 = loadProgram ( " vs_shadowvolume_svback " , " fs_shadowvolume_svbacktex1 " ) ;
m_programBackTex2 = loadProgram ( " vs_shadowvolume_svback " , " fs_shadowvolume_svbacktex2 " ) ;
m_programFrontTex1 = loadProgram ( " vs_shadowvolume_svfront " , " fs_shadowvolume_svfronttex1 " ) ;
m_programFrontTex2 = loadProgram ( " vs_shadowvolume_svfront " , " fs_shadowvolume_svfronttex2 " ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : ProgramHandle svProgs [ ShadowVolumeProgramType : : Count ] [ ShadowVolumePart : : Count ] =
2013-10-20 22:34:28 +04:00
{
2017-06-15 19:57:08 +03:00
{ m_programBackBlank , m_programSideBlank , m_programFrontBlank } , // Blank
{ m_programBackColor , m_programSideColor , m_programFrontColor } , // Color
{ m_programBackTex1 , m_programSideTex , m_programFrontTex1 } , // Tex1
{ m_programBackTex2 , m_programSideTex , m_programFrontTex2 } , // Tex2
} ;
bx : : memCopy ( m_svProgs , svProgs , sizeof ( svProgs ) ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_bunnyHighPolyModel . load ( " meshes/bunny_patched.bin " ) ;
m_bunnyHighPolyModel . m_program = m_programColorLighting ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_bunnyLowPolyModel . load ( " meshes/bunny_decimated.bin " ) ;
m_bunnyLowPolyModel . m_program = m_programColorLighting ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_columnModel . load ( " meshes/column.bin " ) ;
m_columnModel . m_program = m_programColorLighting ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_platformModel . load ( " meshes/platform.bin " ) ;
m_platformModel . m_program = m_programTextureLighting ;
m_platformModel . m_texture = m_figureTex ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_cubeModel . load ( " meshes/cube.bin " ) ;
m_cubeModel . m_program = m_programTextureLighting ;
m_cubeModel . m_texture = m_figureTex ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:56:13 +03:00
m_hplaneFieldModel . load ( s_hplaneVertices
, BX_COUNTOF ( s_hplaneVertices )
, PosNormalTexcoordVertex : : ms_decl
, s_planeIndices
, BX_COUNTOF ( s_planeIndices )
) ;
2017-06-15 19:57:08 +03:00
m_hplaneFieldModel . m_program = m_programTextureLighting ;
m_hplaneFieldModel . m_texture = m_fieldstoneTex ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:56:13 +03:00
m_hplaneFigureModel . load ( s_hplaneVertices
, BX_COUNTOF ( s_hplaneVertices )
, PosNormalTexcoordVertex : : ms_decl
, s_planeIndices
, BX_COUNTOF ( s_planeIndices )
) ;
2017-06-15 19:57:08 +03:00
m_hplaneFigureModel . m_program = m_programTextureLighting ;
m_hplaneFigureModel . m_texture = m_figureTex ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:56:13 +03:00
m_vplaneModel . load ( s_vplaneVertices
, BX_COUNTOF ( s_vplaneVertices )
, PosNormalTexcoordVertex : : ms_decl
, s_planeIndices
, BX_COUNTOF ( s_planeIndices )
) ;
2017-06-15 19:57:08 +03:00
m_vplaneModel . m_program = m_programColorTexture ;
m_vplaneModel . m_texture = m_flareTex ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Setup lights.
const float rgbInnerR [ MAX_LIGHTS_COUNT ] [ 4 ] =
2013-10-20 22:34:28 +04:00
{
2017-06-15 19:57:08 +03:00
{ 1.0f , 0.7f , 0.2f , 0.0f } , //yellow
{ 0.7f , 0.2f , 1.0f , 0.0f } , //purple
{ 0.2f , 1.0f , 0.7f , 0.0f } , //cyan
{ 1.0f , 0.4f , 0.2f , 0.0f } , //orange
{ 0.7f , 0.7f , 0.7f , 0.0f } , //white
} ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
for ( uint8_t ii = 0 , jj = 0 ; ii < MAX_LIGHTS_COUNT ; + + ii , + + jj )
2013-10-20 22:34:28 +04:00
{
2017-06-15 19:57:08 +03:00
const uint8_t index = jj % MAX_LIGHTS_COUNT ;
m_lightRgbInnerR [ ii ] [ 0 ] = rgbInnerR [ index ] [ 0 ] ;
m_lightRgbInnerR [ ii ] [ 1 ] = rgbInnerR [ index ] [ 1 ] ;
m_lightRgbInnerR [ ii ] [ 2 ] = rgbInnerR [ index ] [ 2 ] ;
m_lightRgbInnerR [ ii ] [ 3 ] = rgbInnerR [ index ] [ 3 ] ;
2013-10-20 22:34:28 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_profTime = 0 ;
m_timeOffset = bx : : getHPCounter ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_numShadowVolumeVertices = 0 ;
m_numShadowVolumeIndices = 0 ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_oldWidth = 0 ;
m_oldHeight = 0 ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Imgui.
2017-06-21 06:56:13 +03:00
m_settings_showHelp = false ;
m_settings_updateLights = true ;
m_settings_updateScene = true ;
m_settings_mixedSvImpl = true ;
m_settings_useStencilTexture = false ;
m_settings_drawShadowVolumes = false ;
2017-06-21 06:37:43 +03:00
m_settings_numLights = 1 ;
m_settings_instanceCount = 9 ;
2017-06-15 19:57:08 +03:00
m_settings_shadowVolumeImpl = ShadowVolumeImpl : : DepthFail ;
m_settings_shadowVolumeAlgorithm = ShadowVolumeAlgorithm : : EdgeBased ;
m_scrollAreaRight = 0 ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_lightPattern = LightPattern0 ;
2017-06-21 06:56:13 +03:00
m_currentMesh = BunnyLowPoly ;
2017-06-15 19:57:08 +03:00
m_currentScene = Scene0 ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Set view matrix
cameraCreate ( ) ;
2017-06-21 06:56:13 +03:00
float initialPos [ 3 ] = { 3.0f , 20.0f , - 58.0f } ;
2017-06-15 19:57:08 +03:00
cameraSetPosition ( initialPos ) ;
cameraSetVerticalAngle ( - 0.25f ) ;
cameraGetViewMtx ( m_viewState . m_view ) ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
virtual int shutdown ( ) BX_OVERRIDE
{
// Cleanup
m_bunnyLowPolyModel . unload ( ) ;
m_bunnyHighPolyModel . unload ( ) ;
m_columnModel . unload ( ) ;
m_cubeModel . unload ( ) ;
m_platformModel . unload ( ) ;
m_hplaneFieldModel . unload ( ) ;
m_hplaneFigureModel . unload ( ) ;
m_vplaneModel . unload ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
s_uniforms . destroy ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : destroyUniform ( s_texColor ) ;
bgfx : : destroyUniform ( s_texStencil ) ;
bgfx : : destroyFrameBuffer ( s_stencilFb ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : destroyTexture ( m_figureTex ) ;
bgfx : : destroyTexture ( m_fieldstoneTex ) ;
bgfx : : destroyTexture ( m_flareTex ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : destroyProgram ( m_programTextureLighting ) ;
bgfx : : destroyProgram ( m_programColorLighting ) ;
bgfx : : destroyProgram ( m_programColorTexture ) ;
bgfx : : destroyProgram ( m_programTexture ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : destroyProgram ( m_programBackBlank ) ;
bgfx : : destroyProgram ( m_programSideBlank ) ;
bgfx : : destroyProgram ( m_programFrontBlank ) ;
bgfx : : destroyProgram ( m_programBackColor ) ;
bgfx : : destroyProgram ( m_programSideColor ) ;
bgfx : : destroyProgram ( m_programFrontColor ) ;
bgfx : : destroyProgram ( m_programSideTex ) ;
bgfx : : destroyProgram ( m_programBackTex1 ) ;
bgfx : : destroyProgram ( m_programBackTex2 ) ;
bgfx : : destroyProgram ( m_programFrontTex1 ) ;
bgfx : : destroyProgram ( m_programFrontTex2 ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
cameraDestroy ( ) ;
imguiDestroy ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Shutdown bgfx.
bgfx : : shutdown ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
return 0 ;
}
2013-10-18 09:55:43 +04:00
2017-06-15 19:57:08 +03:00
bool update ( ) BX_OVERRIDE
{
if ( ! entry : : processEvents ( m_viewState . m_width , m_viewState . m_height , m_debug , m_reset , & m_mouseState ) )
2013-10-18 09:55:43 +04:00
{
2017-06-15 19:57:08 +03:00
s_uniforms . submitConstUniforms ( ) ;
// Set projection matrices.
const float fov = 60.0f ;
const float aspect = float ( m_viewState . m_width ) / float ( m_viewState . m_height ) ;
const float nearPlane = 1.0f ;
const float farPlane = 1000.0f ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Respond properly on resize.
if ( m_oldWidth ! = m_viewState . m_width
2017-06-21 06:42:46 +03:00
| | m_oldHeight ! = m_viewState . m_height )
2013-10-20 22:34:28 +04:00
{
2017-06-15 19:57:08 +03:00
m_oldWidth = m_viewState . m_width ;
m_oldHeight = m_viewState . m_height ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : destroyFrameBuffer ( s_stencilFb ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : TextureHandle fbtextures [ ] =
{
bgfx : : createTexture2D ( uint16_t ( m_viewState . m_width ) , uint16_t ( m_viewState . m_height ) , false , 1 , bgfx : : TextureFormat : : BGRA8 , BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | BGFX_TEXTURE_RT ) ,
bgfx : : createTexture2D ( uint16_t ( m_viewState . m_width ) , uint16_t ( m_viewState . m_height ) , false , 1 , bgfx : : TextureFormat : : D16 , BGFX_TEXTURE_RT_WRITE_ONLY )
} ;
s_stencilFb = bgfx : : createFrameBuffer ( BX_COUNTOF ( fbtextures ) , fbtextures , true ) ;
2013-10-20 22:34:28 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Time.
int64_t now = bx : : getHPCounter ( ) ;
static int64_t last = now ;
const int64_t frameTime = now - last ;
last = now ;
const double freq = double ( bx : : getHPFrequency ( ) ) ;
const double toMs = 1000.0 / freq ;
float time = ( float ) ( ( now - m_timeOffset ) / double ( bx : : getHPFrequency ( ) ) ) ;
const float deltaTime = float ( frameTime / freq ) ;
s_uniforms . m_time = time ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Update camera.
cameraUpdate ( deltaTime , m_mouseState ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Set view and projection matrix for view 0.
const bgfx : : HMD * hmd = bgfx : : getHMD ( ) ;
if ( NULL ! = hmd & & 0 ! = ( hmd - > flags & BGFX_HMD_RENDERING ) )
2013-10-20 22:34:28 +04:00
{
2017-06-15 19:57:08 +03:00
float eye [ 3 ] ;
cameraGetPosition ( eye ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bx : : mtxQuatTranslationHMD ( m_viewState . m_view , hmd - > eye [ 0 ] . rotation , eye ) ;
bx : : mtxProj ( m_viewState . m_proj , hmd - > eye [ 0 ] . fov , nearPlane , farPlane , s_oglNdc ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_viewState . m_width = hmd - > width ;
m_viewState . m_height = hmd - > height ;
2013-10-20 22:34:28 +04:00
}
2017-06-15 19:57:08 +03:00
else
{
cameraGetViewMtx ( m_viewState . m_view ) ;
bx : : mtxProj ( m_viewState . m_proj , fov , aspect , nearPlane , farPlane , s_oglNdc ) ;
}
2017-06-15 21:25:05 +03:00
2017-06-21 06:42:46 +03:00
imguiBeginFrame (
m_mouseState . m_mx
, m_mouseState . m_my
, ( m_mouseState . m_buttons [ entry : : MouseButton : : Left ] ? IMGUI_MBUT_LEFT : 0 )
| ( m_mouseState . m_buttons [ entry : : MouseButton : : Right ] ? IMGUI_MBUT_RIGHT : 0 )
| ( m_mouseState . m_buttons [ entry : : MouseButton : : Middle ] ? IMGUI_MBUT_MIDDLE : 0 )
, m_mouseState . m_mz
, uint16_t ( m_viewState . m_width )
, uint16_t ( m_viewState . m_height )
) ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
ImGui : : SetNextWindowPos ( ImVec2 ( m_viewState . m_width - 256.0f , 10.0f ) ) ;
ImGui : : Begin ( " Settings "
2017-06-21 06:56:13 +03:00
, NULL
, ImVec2 ( 256.0f , 700.0f )
, ImGuiWindowFlags_AlwaysAutoResize
) ;
2017-06-21 06:32:02 +03:00
2017-06-15 19:57:08 +03:00
const char * titles [ 2 ] =
{
" Scene 0 " ,
" Scene 1 " ,
} ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
if ( ImGui : : RadioButton ( titles [ Scene0 ] , Scene0 = = m_currentScene ) )
2017-06-15 19:57:08 +03:00
{
m_currentScene = Scene0 ;
}
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
if ( ImGui : : RadioButton ( titles [ Scene1 ] , Scene1 = = m_currentScene ) )
2017-06-15 19:57:08 +03:00
{
m_currentScene = Scene1 ;
}
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
ImGui : : SliderInt ( " Lights " , & m_settings_numLights , 1 , MAX_LIGHTS_COUNT ) ;
ImGui : : Checkbox ( " Update lights " , & m_settings_updateLights ) ;
ImGui : : Indent ( ) ;
2017-06-21 06:32:02 +03:00
2017-06-21 06:37:43 +03:00
if ( ImGui : : RadioButton ( " Light pattern 0 " , LightPattern0 = = m_lightPattern ) )
2017-06-15 19:57:08 +03:00
{
m_lightPattern = LightPattern0 ;
}
2017-06-21 06:32:02 +03:00
2017-06-21 06:37:43 +03:00
if ( ImGui : : RadioButton ( " Light pattern 1 " , LightPattern1 = = m_lightPattern ) )
2017-06-15 19:57:08 +03:00
{
m_lightPattern = LightPattern1 ;
}
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
ImGui : : Unindent ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
if ( Scene0 = = m_currentScene )
2017-06-15 19:57:08 +03:00
{
2017-06-21 06:37:43 +03:00
ImGui : : Checkbox ( " Update scene " , & m_settings_updateScene ) ;
2017-06-15 19:57:08 +03:00
}
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
ImGui : : Separator ( ) ;
2017-06-21 06:32:02 +03:00
2017-06-21 06:37:43 +03:00
ImGui : : Text ( " Stencil buffer implementation: " ) ;
ImGui : : Checkbox ( " Mixed " , & m_settings_mixedSvImpl ) ;
if ( ! m_settings_mixedSvImpl )
{
m_settings_shadowVolumeImpl = ( ImGui : : RadioButton ( " Depth fail " , ShadowVolumeImpl : : DepthFail = = m_settings_shadowVolumeImpl ) ? ShadowVolumeImpl : : DepthFail : m_settings_shadowVolumeImpl ) ;
m_settings_shadowVolumeImpl = ( ImGui : : RadioButton ( " Depth pass " , ShadowVolumeImpl : : DepthPass = = m_settings_shadowVolumeImpl ) ? ShadowVolumeImpl : : DepthPass : m_settings_shadowVolumeImpl ) ;
}
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
ImGui : : Text ( " Shadow volume implementation: " ) ;
m_settings_shadowVolumeAlgorithm = ( ImGui : : RadioButton ( " Face based impl. " , ShadowVolumeAlgorithm : : FaceBased = = m_settings_shadowVolumeAlgorithm ) ? ShadowVolumeAlgorithm : : FaceBased : m_settings_shadowVolumeAlgorithm ) ;
m_settings_shadowVolumeAlgorithm = ( ImGui : : RadioButton ( " Edge based impl. " , ShadowVolumeAlgorithm : : EdgeBased = = m_settings_shadowVolumeAlgorithm ) ? ShadowVolumeAlgorithm : : EdgeBased : m_settings_shadowVolumeAlgorithm ) ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
ImGui : : Text ( " Stencil: " ) ;
if ( ImGui : : RadioButton ( " Use stencil buffer " , ! m_settings_useStencilTexture ) )
2017-06-15 19:57:08 +03:00
{
if ( m_settings_useStencilTexture )
{
m_settings_useStencilTexture = false ;
}
}
2017-06-21 06:37:43 +03:00
if ( ImGui : : RadioButton ( " Use texture as stencil " , m_settings_useStencilTexture ) )
2017-06-15 19:57:08 +03:00
{
if ( ! m_settings_useStencilTexture )
{
m_settings_useStencilTexture = true ;
}
}
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
ImGui : : Separator ( ) ;
ImGui : : Text ( " Mesh: " ) ;
if ( ImGui : : RadioButton ( " Bunny - high poly " , BunnyHighPoly = = m_currentMesh ) )
2017-06-15 19:57:08 +03:00
{
m_currentMesh = BunnyHighPoly ;
}
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
if ( ImGui : : RadioButton ( " Bunny - low poly " , BunnyLowPoly = = m_currentMesh ) )
2017-06-15 19:57:08 +03:00
{
m_currentMesh = BunnyLowPoly ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
if ( Scene1 = = m_currentScene )
{
2017-06-21 06:37:43 +03:00
ImGui : : SliderInt ( " Instance count " , & m_settings_instanceCount , 1 , MAX_INSTANCE_COUNT ) ;
2017-06-15 19:57:08 +03:00
}
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
ImGui : : Text ( " CPU Time: %7.1f [ms] " , double ( m_profTime ) * toMs ) ;
ImGui : : Text ( " Volume Vertices: %5.uk " , m_numShadowVolumeVertices / 1000 ) ;
ImGui : : Text ( " Volume Indices: %6.uk " , m_numShadowVolumeIndices / 1000 ) ;
2017-06-15 19:57:08 +03:00
m_numShadowVolumeVertices = 0 ;
m_numShadowVolumeIndices = 0 ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
ImGui : : Separator ( ) ;
ImGui : : Checkbox ( " Draw Shadow Volumes " , & m_settings_drawShadowVolumes ) ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
ImGui : : End ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:42:46 +03:00
ImGui : : SetNextWindowPos ( ImVec2 ( 10 , float ( m_viewState . m_height ) - 77.0f - 10.0f ) ) ;
2017-06-21 06:37:43 +03:00
ImGui : : Begin ( " Show help: "
2017-06-21 06:42:46 +03:00
, NULL
, ImVec2 ( 120.0f , 77.0f )
, ImGuiWindowFlags_AlwaysAutoResize
) ;
2017-06-21 06:32:02 +03:00
2017-06-21 06:42:46 +03:00
if ( ImGui : : Button ( m_settings_showHelp ? " ON " : " OFF " ) )
{
2017-06-21 06:37:43 +03:00
m_settings_showHelp = ! m_settings_showHelp ;
2017-06-21 06:42:46 +03:00
}
2017-06-15 21:25:05 +03:00
2017-06-21 06:37:43 +03:00
ImGui : : End ( ) ;
2017-06-21 06:32:02 +03:00
2017-06-15 19:57:08 +03:00
imguiEndFrame ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
//update settings
s_uniforms . m_params . m_ambientPass = 1.0f ;
s_uniforms . m_params . m_lightingPass = 1.0f ;
s_uniforms . m_params . m_texelHalf = s_texelHalf ;
s_uniforms . m_svparams . m_useStencilTex = float ( m_settings_useStencilTexture ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
//set picked bunny model
Model * bunnyModel = BunnyLowPoly = = m_currentMesh ? & m_bunnyLowPolyModel : & m_bunnyHighPolyModel ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
//update time accumulators
static float sceneTimeAccumulator = 0.0f ;
if ( m_settings_updateScene )
2013-10-20 22:34:28 +04:00
{
2017-06-15 19:57:08 +03:00
sceneTimeAccumulator + = deltaTime ;
2013-10-20 22:34:28 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
static float lightTimeAccumulator = 0.0f ;
if ( m_settings_updateLights )
2013-10-20 22:34:28 +04:00
{
2017-06-15 19:57:08 +03:00
lightTimeAccumulator + = deltaTime ;
2013-10-20 22:34:28 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
//setup light positions
float lightPosRadius [ MAX_LIGHTS_COUNT ] [ 4 ] ;
if ( LightPattern0 = = m_lightPattern )
2013-10-21 00:11:41 +04:00
{
2017-06-15 19:57:08 +03:00
for ( uint8_t ii = 0 ; ii < m_settings_numLights ; + + ii )
{
2017-06-21 06:37:43 +03:00
lightPosRadius [ ii ] [ 0 ] = bx : : fcos ( 2.0f * bx : : kPi / float ( m_settings_numLights ) * float ( ii ) + lightTimeAccumulator * 1.1f + 3.0f ) * 20.0f ;
2017-06-15 19:57:08 +03:00
lightPosRadius [ ii ] [ 1 ] = 20.0f ;
2017-06-21 06:37:43 +03:00
lightPosRadius [ ii ] [ 2 ] = bx : : fsin ( 2.0f * bx : : kPi / float ( m_settings_numLights ) * float ( ii ) + lightTimeAccumulator * 1.1f + 3.0f ) * 20.0f ;
2017-06-15 19:57:08 +03:00
lightPosRadius [ ii ] [ 3 ] = 20.0f ;
}
}
else
{
for ( uint8_t ii = 0 ; ii < m_settings_numLights ; + + ii )
{
2017-06-21 06:37:43 +03:00
lightPosRadius [ ii ] [ 0 ] = bx : : fcos ( float ( ii ) * 2.0f / float ( m_settings_numLights ) + lightTimeAccumulator * 1.3f + bx : : kPi ) * 40.0f ;
2017-06-15 19:57:08 +03:00
lightPosRadius [ ii ] [ 1 ] = 20.0f ;
2017-06-21 06:37:43 +03:00
lightPosRadius [ ii ] [ 2 ] = bx : : fsin ( float ( ii ) * 2.0f / float ( m_settings_numLights ) + lightTimeAccumulator * 1.3f + bx : : kPi ) * 40.0f ;
2017-06-15 19:57:08 +03:00
lightPosRadius [ ii ] [ 3 ] = 20.0f ;
}
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
//use debug font to print information about this example.
bgfx : : dbgTextClear ( ) ;
bgfx : : dbgTextPrintf ( 0 , 1 , 0x4f , " bgfx/examples/14-shadowvolumes " ) ;
bgfx : : dbgTextPrintf ( 0 , 2 , 0x6f , " Description: Shadow volumes. " ) ;
bgfx : : dbgTextPrintf ( 0 , 3 , 0x0f , " Frame: % 7.3f[ms] " , double ( frameTime ) * toMs ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
if ( m_settings_showHelp )
2013-10-18 09:55:43 +04:00
{
2017-06-15 19:57:08 +03:00
uint8_t row = 5 ;
bgfx : : dbgTextPrintf ( 3 , row + + , 0x0f , " Stencil buffer implementation: " ) ;
bgfx : : dbgTextPrintf ( 8 , row + + , 0x0f , " Depth fail - Robust, but slower than 'Depth pass'. Requires computing and drawing of shadow volume caps. " ) ;
bgfx : : dbgTextPrintf ( 8 , row + + , 0x0f , " Depth pass - Faster, but not stable. Shadows are wrong when camera is in the shadow. " ) ;
bgfx : : dbgTextPrintf ( 8 , row + + , 0x0f , " Mixed - 'Depth pass' where possible, 'Depth fail' where necessary. Best of both words. " ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
row + + ;
bgfx : : dbgTextPrintf ( 3 , row + + , 0x0f , " Shadow volume implementation: " ) ;
bgfx : : dbgTextPrintf ( 8 , row + + , 0x0f , " Face Based - Slower. Works fine with either stencil buffer or texture as stencil. " ) ;
bgfx : : dbgTextPrintf ( 8 , row + + , 0x0f , " Edge Based - Faster, but requires +2 incr/decr on stencil buffer. To avoid massive redraw, use RGBA texture as stencil. " ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
row + + ;
bgfx : : dbgTextPrintf ( 3 , row + + , 0x0f , " Stencil: " ) ;
bgfx : : dbgTextPrintf ( 8 , row + + , 0x0f , " Stencil buffer - Faster, but capable only of +1 incr. " ) ;
bgfx : : dbgTextPrintf ( 8 , row + + , 0x0f , " Texture as stencil - Slower, but capable of +2 incr. " ) ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Setup instances
Instance shadowCasters [ SceneCount ] [ 60 ] ;
uint16_t shadowCastersCount [ SceneCount ] ;
for ( uint8_t ii = 0 ; ii < SceneCount ; + + ii )
{
shadowCastersCount [ ii ] = 0 ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
Instance shadowReceivers [ SceneCount ] [ 10 ] ;
uint16_t shadowReceiversCount [ SceneCount ] ;
for ( uint8_t ii = 0 ; ii < SceneCount ; + + ii )
{
shadowReceiversCount [ ii ] = 0 ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Scene 0 - shadow casters - Bunny
{
Instance & inst = shadowCasters [ Scene0 ] [ shadowCastersCount [ Scene0 ] + + ] ;
2013-10-21 00:11:41 +04:00
inst . m_scale [ 0 ] = 5.0f ;
inst . m_scale [ 1 ] = 5.0f ;
inst . m_scale [ 2 ] = 5.0f ;
inst . m_rotation [ 0 ] = 0.0f ;
2017-06-15 19:57:08 +03:00
inst . m_rotation [ 1 ] = float ( 4.0f - sceneTimeAccumulator * 0.7f ) ;
2013-10-21 00:11:41 +04:00
inst . m_rotation [ 2 ] = 0.0f ;
2017-06-15 19:57:08 +03:00
inst . m_pos [ 0 ] = 0.0f ;
inst . m_pos [ 1 ] = 10.0f ;
inst . m_pos [ 2 ] = 0.0f ;
inst . m_color [ 0 ] = 0.68f ;
inst . m_color [ 1 ] = 0.65f ;
inst . m_color [ 2 ] = 0.60f ;
2013-10-21 00:11:41 +04:00
inst . m_model = bunnyModel ;
2017-06-15 19:57:08 +03:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Scene 0 - shadow casters - Cubes top.
const uint8_t numCubesTop = 9 ;
for ( uint16_t ii = 0 ; ii < numCubesTop ; + + ii )
{
Instance & inst = shadowCasters [ Scene0 ] [ shadowCastersCount [ Scene0 ] + + ] ;
inst . m_scale [ 0 ] = 1.0f ;
inst . m_scale [ 1 ] = 1.0f ;
inst . m_scale [ 2 ] = 1.0f ;
inst . m_rotation [ 0 ] = 0.0f ;
inst . m_rotation [ 1 ] = 0.0f ;
inst . m_rotation [ 2 ] = 0.0f ;
inst . m_pos [ 0 ] = bx : : fsin ( ii * 2.0f + 13.0f + sceneTimeAccumulator * 1.1f ) * 13.0f ;
inst . m_pos [ 1 ] = 6.0f ;
inst . m_pos [ 2 ] = bx : : fcos ( ii * 2.0f + 13.0f + sceneTimeAccumulator * 1.1f ) * 13.0f ;
inst . m_model = & m_cubeModel ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Scene 0 - shadow casters - Cubes bottom.
const uint8_t numCubesBottom = 9 ;
for ( uint16_t ii = 0 ; ii < numCubesBottom ; + + ii )
{
Instance & inst = shadowCasters [ Scene0 ] [ shadowCastersCount [ Scene0 ] + + ] ;
inst . m_scale [ 0 ] = 1.0f ;
inst . m_scale [ 1 ] = 1.0f ;
inst . m_scale [ 2 ] = 1.0f ;
inst . m_rotation [ 0 ] = 0.0f ;
inst . m_rotation [ 1 ] = 0.0f ;
inst . m_rotation [ 2 ] = 0.0f ;
inst . m_pos [ 0 ] = bx : : fsin ( ii * 2.0f + 13.0f + sceneTimeAccumulator * 1.1f ) * 13.0f ;
inst . m_pos [ 1 ] = 22.0f ;
inst . m_pos [ 2 ] = bx : : fcos ( ii * 2.0f + 13.0f + sceneTimeAccumulator * 1.1f ) * 13.0f ;
inst . m_model = & m_cubeModel ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Scene 0 - shadow casters - Columns.
const float dist = 16.0f ;
const float columnPositions [ ] [ 3 ] =
{
{ dist , 3.3f , dist } ,
{ - dist , 3.3f , dist } ,
{ dist , 3.3f , - dist } ,
{ - dist , 3.3f , - dist } ,
} ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
for ( uint8_t ii = 0 ; ii < 4 ; + + ii )
{
Instance & inst = shadowCasters [ Scene0 ] [ shadowCastersCount [ Scene0 ] + + ] ;
inst . m_scale [ 0 ] = 1.5f ;
inst . m_scale [ 1 ] = 1.5f ;
inst . m_scale [ 2 ] = 1.5f ;
inst . m_rotation [ 0 ] = 0.0f ;
inst . m_rotation [ 1 ] = 1.57f ;
inst . m_rotation [ 2 ] = 0.0f ;
inst . m_pos [ 0 ] = columnPositions [ ii ] [ 0 ] ;
inst . m_pos [ 1 ] = columnPositions [ ii ] [ 1 ] ;
inst . m_pos [ 2 ] = columnPositions [ ii ] [ 2 ] ;
inst . m_color [ 0 ] = 0.25f ;
inst . m_color [ 1 ] = 0.25f ;
inst . m_color [ 2 ] = 0.25f ;
inst . m_model = & m_columnModel ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Scene 0 - shadow casters - Ceiling.
{
Instance & inst = shadowCasters [ Scene0 ] [ shadowCastersCount [ Scene0 ] + + ] ;
inst . m_scale [ 0 ] = 21.0f ;
inst . m_scale [ 1 ] = 21.0f ;
inst . m_scale [ 2 ] = 21.0f ;
inst . m_rotation [ 0 ] = bx : : kPi ;
inst . m_rotation [ 1 ] = 0.0f ;
inst . m_rotation [ 2 ] = 0.0f ;
inst . m_pos [ 0 ] = 0.0f ;
inst . m_pos [ 1 ] = 28.2f ;
inst . m_pos [ 2 ] = 0.0f ;
inst . m_model = & m_platformModel ;
inst . m_svExtrusionDistance = 2.0f ; //prevent culling on tight view frustum
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Scene 0 - shadow casters - Platform.
{
Instance & inst = shadowCasters [ Scene0 ] [ shadowCastersCount [ Scene0 ] + + ] ;
inst . m_scale [ 0 ] = 24.0f ;
inst . m_scale [ 1 ] = 24.0f ;
inst . m_scale [ 2 ] = 24.0f ;
inst . m_rotation [ 0 ] = 0.0f ;
inst . m_rotation [ 1 ] = 0.0f ;
inst . m_rotation [ 2 ] = 0.0f ;
inst . m_pos [ 0 ] = 0.0f ;
inst . m_pos [ 1 ] = 0.0f ;
inst . m_pos [ 2 ] = 0.0f ;
inst . m_model = & m_platformModel ;
inst . m_svExtrusionDistance = 2.0f ; //prevent culling on tight view frustum
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Scene 0 - shadow receivers - Floor.
{
Instance & inst = shadowReceivers [ Scene0 ] [ shadowReceiversCount [ Scene0 ] + + ] ;
inst . m_scale [ 0 ] = 500.0f ;
inst . m_scale [ 1 ] = 500.0f ;
inst . m_scale [ 2 ] = 500.0f ;
inst . m_rotation [ 0 ] = 0.0f ;
inst . m_rotation [ 1 ] = 0.0f ;
inst . m_rotation [ 2 ] = 0.0f ;
inst . m_pos [ 0 ] = 0.0f ;
inst . m_pos [ 1 ] = 0.0f ;
inst . m_pos [ 2 ] = 0.0f ;
inst . m_model = & m_hplaneFieldModel ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Scene 1 - shadow casters - Bunny instances
{
enum Direction
2013-10-21 00:11:41 +04:00
{
2017-06-15 19:57:08 +03:00
Left = 0x0 ,
Down = 0x1 ,
Right = 0x2 ,
Up = 0x3 ,
} ;
const uint8_t directionMask = 0x3 ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
uint8_t currentDirection = Left ;
float currX = 0.0f ;
float currY = 0.0f ;
const float stepX = 20.0f ;
const float stepY = 20.0f ;
uint8_t stateStep = 0 ;
uint8_t stateChange = 1 ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
for ( uint8_t ii = 0 ; ii < m_settings_instanceCount ; + + ii )
2013-10-21 00:11:41 +04:00
{
2017-06-15 19:57:08 +03:00
Instance & inst = shadowCasters [ Scene1 ] [ shadowCastersCount [ Scene1 ] + + ] ;
inst . m_scale [ 0 ] = 5.0f ;
inst . m_scale [ 1 ] = 5.0f ;
inst . m_scale [ 2 ] = 5.0f ;
inst . m_rotation [ 0 ] = 0.0f ;
inst . m_rotation [ 1 ] = bx : : kPi ;
inst . m_rotation [ 2 ] = 0.0f ;
inst . m_pos [ 0 ] = currX ;
inst . m_pos [ 1 ] = 0.0f ;
inst . m_pos [ 2 ] = currY ;
inst . m_model = bunnyModel ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
+ + stateStep ;
if ( stateStep > = ( ( stateChange & ~ 0x1 ) > > 1 ) )
{
currentDirection = ( currentDirection + 1 ) & directionMask ;
stateStep = 0 ;
+ + stateChange ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
switch ( currentDirection )
{
2017-06-21 06:56:13 +03:00
case Left : currX - = stepX ; break ;
case Down : currY - = stepY ; break ;
case Right : currX + = stepX ; break ;
case Up : currY + = stepY ; break ;
2017-06-15 19:57:08 +03:00
}
2013-10-21 00:11:41 +04:00
}
2013-10-18 09:55:43 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Scene 1 - shadow receivers - Floor.
2013-10-18 09:55:43 +04:00
{
2017-06-15 19:57:08 +03:00
Instance & inst = shadowReceivers [ Scene1 ] [ shadowReceiversCount [ Scene1 ] + + ] ;
inst . m_scale [ 0 ] = 500.0f ;
inst . m_scale [ 1 ] = 500.0f ;
inst . m_scale [ 2 ] = 500.0f ;
inst . m_rotation [ 0 ] = 0.0f ;
inst . m_rotation [ 1 ] = 0.0f ;
inst . m_rotation [ 2 ] = 0.0f ;
inst . m_pos [ 0 ] = 0.0f ;
inst . m_pos [ 1 ] = 0.0f ;
inst . m_pos [ 2 ] = 0.0f ;
inst . m_model = & m_hplaneFigureModel ;
2013-10-18 09:55:43 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Make sure at the beginning everything gets cleared.
bgfx : : setViewClear ( 0
2017-06-21 06:42:46 +03:00
, BGFX_CLEAR_COLOR
| BGFX_CLEAR_DEPTH
| BGFX_CLEAR_STENCIL
, m_clearValues . m_clearRgba
, m_clearValues . m_clearDepth
, m_clearValues . m_clearStencil
) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
: : touch ( 0 ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Draw ambient only.
s_uniforms . m_params . m_ambientPass = 1.0f ;
s_uniforms . m_params . m_lightingPass = 0.0f ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
s_uniforms . m_color [ 0 ] = 1.0f ;
s_uniforms . m_color [ 1 ] = 1.0f ;
s_uniforms . m_color [ 2 ] = 1.0f ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:42:46 +03:00
const RenderState & drawAmbient = m_settings_useStencilTexture
? s_renderStates [ RenderState : : ShadowVolume_UsingStencilTexture_DrawAmbient ]
: s_renderStates [ RenderState : : ShadowVolume_UsingStencilBuffer_DrawAmbient ]
;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Draw shadow casters.
for ( uint8_t ii = 0 ; ii < shadowCastersCount [ m_currentScene ] ; + + ii )
2013-10-18 09:55:43 +04:00
{
2017-06-15 19:57:08 +03:00
shadowCasters [ m_currentScene ] [ ii ] . submit ( VIEWID_RANGE1_PASS0 , drawAmbient ) ;
2013-10-18 09:55:43 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Draw shadow receivers.
for ( uint8_t ii = 0 ; ii < shadowReceiversCount [ m_currentScene ] ; + + ii )
2013-10-18 09:55:43 +04:00
{
2017-06-15 19:57:08 +03:00
shadowReceivers [ m_currentScene ] [ ii ] . submit ( VIEWID_RANGE1_PASS0 , drawAmbient ) ;
2013-10-18 09:55:43 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Using stencil texture requires rendering to separate render target. first pass is building depth buffer.
if ( m_settings_useStencilTexture )
2013-10-18 09:55:43 +04:00
{
2017-06-15 19:57:08 +03:00
bgfx : : setViewClear ( VIEWID_RANGE1_RT_PASS1 , BGFX_CLEAR_DEPTH , 0x00000000 , 1.0f , 0 ) ;
bgfx : : setViewFrameBuffer ( VIEWID_RANGE1_RT_PASS1 , s_stencilFb ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
const RenderState & renderState = s_renderStates [ RenderState : : ShadowVolume_UsingStencilTexture_BuildDepth ] ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
for ( uint8_t ii = 0 ; ii < shadowCastersCount [ m_currentScene ] ; + + ii )
{
shadowCasters [ m_currentScene ] [ ii ] . submit ( VIEWID_RANGE1_RT_PASS1 , renderState ) ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
for ( uint8_t ii = 0 ; ii < shadowReceiversCount [ m_currentScene ] ; + + ii )
{
shadowReceivers [ m_currentScene ] [ ii ] . submit ( VIEWID_RANGE1_RT_PASS1 , renderState ) ;
}
2013-10-18 09:55:43 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_profTime = bx : : getHPCounter ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
/**
* For each light :
* 1. Compute and draw shadow volume to stencil buffer
* 2. Draw diffuse with stencil test
*/
for ( uint8_t ii = 0 , viewId = VIEWID_RANGE15_PASS2 ; ii < m_settings_numLights ; + + ii , + + viewId )
2013-10-18 09:55:43 +04:00
{
2017-06-15 19:57:08 +03:00
const float * lightPos = lightPosRadius [ ii ] ;
2017-06-15 21:25:05 +03:00
2017-06-21 06:42:46 +03:00
bx : : memCopy ( s_uniforms . m_lightPosRadius , lightPosRadius [ ii ] , 4 * sizeof ( float ) ) ;
2017-06-15 19:57:08 +03:00
bx : : memCopy ( s_uniforms . m_lightRgbInnerR , m_lightRgbInnerR [ ii ] , 3 * sizeof ( float ) ) ;
bx : : memCopy ( s_uniforms . m_color , m_lightRgbInnerR [ ii ] , 3 * sizeof ( float ) ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
if ( m_settings_useStencilTexture )
{
bgfx : : setViewFrameBuffer ( viewId , s_stencilFb ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : setViewClear ( viewId
2017-06-21 06:42:46 +03:00
, BGFX_CLEAR_COLOR
, 0x00000000
, 1.0f
, 0
) ;
2017-06-15 19:57:08 +03:00
}
else
{
const bgfx : : FrameBufferHandle invalid = BGFX_INVALID_HANDLE ;
bgfx : : setViewFrameBuffer ( viewId , invalid ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : setViewClear ( viewId
2017-06-21 06:42:46 +03:00
, BGFX_CLEAR_STENCIL
, m_clearValues . m_clearRgba
, m_clearValues . m_clearDepth
, m_clearValues . m_clearStencil
) ;
2017-06-15 19:57:08 +03:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Create near clip volume for current light.
float nearClipVolume [ 6 * 4 ] = { } ;
float pointLight [ 4 ] ;
if ( m_settings_mixedSvImpl )
2013-11-13 01:20:50 +04:00
{
2017-06-15 19:57:08 +03:00
pointLight [ 0 ] = lightPos [ 0 ] ;
pointLight [ 1 ] = lightPos [ 1 ] ;
pointLight [ 2 ] = lightPos [ 2 ] ;
pointLight [ 3 ] = 1.0f ;
createNearClipVolume ( nearClipVolume , pointLight , m_viewState . m_view , fov , aspect , nearPlane ) ;
2013-10-18 09:55:43 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
for ( uint8_t jj = 0 ; jj < shadowCastersCount [ m_currentScene ] ; + + jj )
2013-10-18 09:55:43 +04:00
{
2017-06-15 19:57:08 +03:00
const Instance & instance = shadowCasters [ m_currentScene ] [ jj ] ;
Model * model = instance . m_model ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
ShadowVolumeImpl : : Enum shadowVolumeImpl = m_settings_shadowVolumeImpl ;
if ( m_settings_mixedSvImpl )
{
// If instance is inside near clip volume, depth fail must be used, else depth pass is fine.
bool isInsideVolume = clipTest ( nearClipVolume , 6 , model - > m_mesh , instance . m_scale , instance . m_pos ) ;
shadowVolumeImpl = ( isInsideVolume ? ShadowVolumeImpl : : DepthFail : ShadowVolumeImpl : : DepthPass ) ;
}
s_uniforms . m_svparams . m_dfail = float ( ShadowVolumeImpl : : DepthFail = = shadowVolumeImpl ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Compute virtual light position for shadow volume generation.
float transformedLightPos [ 3 ] ;
shadowVolumeLightTransform ( transformedLightPos
2017-06-21 06:42:46 +03:00
, instance . m_scale
, instance . m_rotation
, instance . m_pos
, lightPos
) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Set virtual light pos.
bx : : memCopy ( s_uniforms . m_virtualLightPos_extrusionDist , transformedLightPos , 3 * sizeof ( float ) ) ;
s_uniforms . m_virtualLightPos_extrusionDist [ 3 ] = instance . m_svExtrusionDistance ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Compute transform for shadow volume.
float shadowVolumeMtx [ 16 ] ;
bx : : mtxSRT ( shadowVolumeMtx
2017-06-21 06:42:46 +03:00
, instance . m_scale [ 0 ]
, instance . m_scale [ 1 ]
, instance . m_scale [ 2 ]
, instance . m_rotation [ 0 ]
, instance . m_rotation [ 1 ]
, instance . m_rotation [ 2 ]
, instance . m_pos [ 0 ]
, instance . m_pos [ 1 ]
, instance . m_pos [ 2 ]
) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
GroupArray & groups = model - > m_mesh . m_groups ;
const uint16_t stride = model - > m_mesh . m_decl . getStride ( ) ;
for ( GroupArray : : iterator it = groups . begin ( ) , itEnd = groups . end ( ) ; it ! = itEnd ; + + it )
2013-10-18 09:55:43 +04:00
{
2017-06-15 19:57:08 +03:00
Group & group = * it ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Create shadow volume.
ShadowVolume shadowVolume ;
shadowVolumeCreate ( shadowVolume
2017-06-21 06:42:46 +03:00
, group
, stride
, shadowVolumeMtx
, transformedLightPos
, shadowVolumeImpl
, m_settings_shadowVolumeAlgorithm
, m_settings_useStencilTexture
) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_numShadowVolumeVertices + = shadowVolume . m_numVertices ;
m_numShadowVolumeIndices + = shadowVolume . m_numIndices ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
ShadowVolumeProgramType : : Enum programIndex = ShadowVolumeProgramType : : Blank ;
RenderState : : Enum renderStateIndex ;
if ( m_settings_useStencilTexture )
{
renderStateIndex = ShadowVolumeImpl : : DepthFail = = shadowVolumeImpl
2017-06-21 06:42:46 +03:00
? RenderState : : ShadowVolume_UsingStencilTexture_CraftStencil_DepthFail
: RenderState : : ShadowVolume_UsingStencilTexture_CraftStencil_DepthPass
;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
programIndex = ShadowVolumeAlgorithm : : FaceBased = = m_settings_shadowVolumeAlgorithm
2017-06-21 06:42:46 +03:00
? ShadowVolumeProgramType : : Tex1
: ShadowVolumeProgramType : : Tex2
;
2017-06-15 19:57:08 +03:00
}
else
{
renderStateIndex = ShadowVolumeImpl : : DepthFail = = shadowVolumeImpl
2017-06-21 06:42:46 +03:00
? RenderState : : ShadowVolume_UsingStencilBuffer_CraftStencil_DepthFail
: RenderState : : ShadowVolume_UsingStencilBuffer_CraftStencil_DepthPass
;
2017-06-15 19:57:08 +03:00
}
const RenderState & renderStateCraftStencil = s_renderStates [ renderStateIndex ] ;
2017-06-15 21:25:05 +03:00
2013-10-18 09:55:43 +04:00
s_uniforms . submitPerDrawUniforms ( ) ;
bgfx : : setTransform ( shadowVolumeMtx ) ;
2017-05-14 21:48:59 +03:00
bgfx : : setVertexBuffer ( 0 , shadowVolume . m_vbSides ) ;
2013-10-18 09:55:43 +04:00
bgfx : : setIndexBuffer ( shadowVolume . m_ibSides ) ;
2017-06-15 19:57:08 +03:00
setRenderState ( renderStateCraftStencil ) ;
: : submit ( viewId , m_svProgs [ programIndex ] [ ShadowVolumePart : : Side ] ) ;
2017-06-15 21:25:05 +03:00
2013-10-18 09:55:43 +04:00
if ( shadowVolume . m_cap )
{
s_uniforms . submitPerDrawUniforms ( ) ;
bgfx : : setTransform ( shadowVolumeMtx ) ;
2017-05-14 21:48:59 +03:00
bgfx : : setVertexBuffer ( 0 , group . m_vbh ) ;
2013-10-18 09:55:43 +04:00
bgfx : : setIndexBuffer ( shadowVolume . m_ibFrontCap ) ;
2017-06-15 19:57:08 +03:00
setRenderState ( renderStateCraftStencil ) ;
: : submit ( viewId , m_svProgs [ programIndex ] [ ShadowVolumePart : : Front ] ) ;
2017-06-15 21:25:05 +03:00
2013-10-18 09:55:43 +04:00
s_uniforms . submitPerDrawUniforms ( ) ;
bgfx : : setTransform ( shadowVolumeMtx ) ;
2017-05-14 21:48:59 +03:00
bgfx : : setVertexBuffer ( 0 , group . m_vbh ) ;
2013-10-18 09:55:43 +04:00
bgfx : : setIndexBuffer ( shadowVolume . m_ibBackCap ) ;
2017-06-15 19:57:08 +03:00
: : setRenderState ( renderStateCraftStencil ) ;
: : submit ( viewId , m_svProgs [ programIndex ] [ ShadowVolumePart : : Back ] ) ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
if ( m_settings_drawShadowVolumes )
{
const RenderState & renderState = s_renderStates [ RenderState : : Custom_DrawShadowVolume_Lines ] ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
s_uniforms . submitPerDrawUniforms ( ) ;
bgfx : : setTransform ( shadowVolumeMtx ) ;
bgfx : : setVertexBuffer ( 0 , shadowVolume . m_vbSides ) ;
bgfx : : setIndexBuffer ( shadowVolume . m_ibSides ) ;
2013-10-18 09:55:43 +04:00
: : setRenderState ( renderState ) ;
2017-06-15 19:57:08 +03:00
: : submit ( VIEWID_RANGE1_PASS3 , m_svProgs [ ShadowVolumeProgramType : : Color ] [ ShadowVolumePart : : Side ] ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
if ( shadowVolume . m_cap )
{
s_uniforms . submitPerDrawUniforms ( ) ;
bgfx : : setTransform ( shadowVolumeMtx ) ;
bgfx : : setVertexBuffer ( 0 , group . m_vbh ) ;
bgfx : : setIndexBuffer ( shadowVolume . m_ibFrontCap ) ;
: : setRenderState ( renderState ) ;
: : submit ( VIEWID_RANGE1_PASS3 , m_svProgs [ ShadowVolumeProgramType : : Color ] [ ShadowVolumePart : : Front ] ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
s_uniforms . submitPerDrawUniforms ( ) ;
bgfx : : setTransform ( shadowVolumeMtx ) ;
bgfx : : setVertexBuffer ( 0 , group . m_vbh ) ;
bgfx : : setIndexBuffer ( shadowVolume . m_ibBackCap ) ;
: : setRenderState ( renderState ) ;
: : submit ( VIEWID_RANGE1_PASS3 , m_svProgs [ ShadowVolumeProgramType : : Color ] [ ShadowVolumePart : : Back ] ) ;
}
2013-10-18 09:55:43 +04:00
}
}
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Draw diffuse only.
s_uniforms . m_params . m_ambientPass = 0.0f ;
s_uniforms . m_params . m_lightingPass = 1.0f ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
RenderState & drawDiffuse = m_settings_useStencilTexture
2017-06-21 06:42:46 +03:00
? s_renderStates [ RenderState : : ShadowVolume_UsingStencilTexture_DrawDiffuse ]
: s_renderStates [ RenderState : : ShadowVolume_UsingStencilBuffer_DrawDiffuse ]
;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// If using stencil texture, viewId is set to render target. Incr it to render to default back buffer.
viewId + = uint8_t ( m_settings_useStencilTexture ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Draw shadow casters.
for ( uint8_t jj = 0 ; jj < shadowCastersCount [ m_currentScene ] ; + + jj )
{
shadowCasters [ m_currentScene ] [ jj ] . submit ( viewId , drawDiffuse ) ;
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Draw shadow receivers.
for ( uint8_t jj = 0 ; jj < shadowReceiversCount [ m_currentScene ] ; + + jj )
{
shadowReceivers [ m_currentScene ] [ jj ] . submit ( viewId , drawDiffuse ) ;
}
2013-10-18 09:55:43 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_profTime = bx : : getHPCounter ( ) - m_profTime ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Lights.
const float lightScale [ 3 ] = { 1.5f , 1.5f , 1.5f } ;
for ( uint8_t ii = 0 ; ii < m_settings_numLights ; + + ii )
2013-10-18 09:55:43 +04:00
{
2017-06-15 19:57:08 +03:00
bx : : memCopy ( s_uniforms . m_color , m_lightRgbInnerR [ ii ] , 3 * sizeof ( float ) ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
float lightMtx [ 16 ] ;
mtxBillboard ( lightMtx , m_viewState . m_view , lightPosRadius [ ii ] , lightScale ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
m_vplaneModel . submit ( VIEWID_RANGE1_PASS3 , lightMtx , s_renderStates [ RenderState : : Custom_BlendLightTexture ] ) ;
2013-10-18 09:55:43 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Setup view rect and transform for all used views.
setViewRectMask ( s_viewMask , 0 , 0 , uint16_t ( m_viewState . m_width ) , uint16_t ( m_viewState . m_height ) ) ;
setViewTransformMask ( s_viewMask , m_viewState . m_view , m_viewState . m_proj ) ;
s_viewMask = 0 ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.
bgfx : : frame ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Swap memory pages.
s_svAllocator . swap ( ) ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
// Reset clear values.
setViewClearMask ( UINT32_MAX
2017-06-21 06:42:46 +03:00
, BGFX_CLEAR_NONE
, m_clearValues . m_clearRgba
, m_clearValues . m_clearDepth
, m_clearValues . m_clearStencil
) ;
2017-06-15 19:57:08 +03:00
return true ;
2013-10-18 09:55:43 +04:00
}
2017-06-21 06:42:46 +03:00
2017-06-15 19:57:08 +03:00
return false ;
2013-10-18 09:55:43 +04:00
}
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
ViewState m_viewState ;
ClearValues m_clearValues ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
uint32_t m_debug ;
uint32_t m_reset ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : TextureHandle m_figureTex ;
bgfx : : TextureHandle m_flareTex ;
bgfx : : TextureHandle m_fieldstoneTex ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : ProgramHandle m_programTextureLighting ;
bgfx : : ProgramHandle m_programColorLighting ;
bgfx : : ProgramHandle m_programColorTexture ;
bgfx : : ProgramHandle m_programTexture ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : ProgramHandle m_programBackBlank ;
bgfx : : ProgramHandle m_programSideBlank ;
bgfx : : ProgramHandle m_programFrontBlank ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : ProgramHandle m_programBackColor ;
bgfx : : ProgramHandle m_programSideColor ;
bgfx : : ProgramHandle m_programFrontColor ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : ProgramHandle m_programSideTex ;
bgfx : : ProgramHandle m_programBackTex1 ;
bgfx : : ProgramHandle m_programBackTex2 ;
bgfx : : ProgramHandle m_programFrontTex1 ;
bgfx : : ProgramHandle m_programFrontTex2 ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bgfx : : ProgramHandle m_svProgs [ ShadowVolumeProgramType : : Count ] [ ShadowVolumePart : : Count ] ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
Model m_bunnyLowPolyModel ;
Model m_bunnyHighPolyModel ;
Model m_columnModel ;
Model m_platformModel ;
Model m_cubeModel ;
Model m_hplaneFieldModel ;
Model m_hplaneFigureModel ;
Model m_vplaneModel ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
float m_lightRgbInnerR [ MAX_LIGHTS_COUNT ] [ 4 ] ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
int64_t m_profTime ;
int64_t m_timeOffset ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
uint32_t m_numShadowVolumeVertices ;
uint32_t m_numShadowVolumeIndices ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
uint32_t m_oldWidth ;
uint32_t m_oldHeight ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
bool m_settings_showHelp ;
bool m_settings_updateLights ;
bool m_settings_updateScene ;
bool m_settings_mixedSvImpl ;
bool m_settings_useStencilTexture ;
bool m_settings_drawShadowVolumes ;
2017-06-21 06:37:43 +03:00
int m_settings_numLights ;
int m_settings_instanceCount ;
2017-06-15 19:57:08 +03:00
ShadowVolumeImpl : : Enum m_settings_shadowVolumeImpl ;
ShadowVolumeAlgorithm : : Enum m_settings_shadowVolumeAlgorithm ;
int32_t m_scrollAreaRight ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
LightPattern m_lightPattern ;
MeshChoice m_currentMesh ;
Scene m_currentScene ;
2017-06-15 21:25:05 +03:00
2017-06-15 19:57:08 +03:00
entry : : MouseState m_mouseState ;
} ;
2013-10-18 09:55:43 +04:00
2017-06-15 19:57:08 +03:00
ENTRY_IMPLEMENT_MAIN ( ExampleShadowVolumes ) ;