2013-12-10 22:37:51 -05:00
/*
2014-01-13 17:45:18 -05:00
* Copyright 2013 - 2014 Dario Manesku . All rights reserved .
2013-12-10 22:37:51 -05:00
* License : http : //www.opensource.org/licenses/BSD-2-Clause
*/
# include <string>
# include <vector>
# include <algorithm>
# include "common.h"
2015-09-18 23:16:24 -04:00
# include <bgfx/bgfx.h>
2013-12-10 22:37:51 -05:00
# include <bx/timer.h>
# include <bx/readerwriter.h>
2014-05-26 22:31:37 -04:00
# include <bx/fpumath.h>
2013-12-10 22:37:51 -05:00
# include "entry/entry.h"
2015-01-08 01:36:36 -05:00
# include "bgfx_utils.h"
2013-12-10 22:37:51 -05:00
2014-01-14 00:48:42 -05:00
# define RENDER_SHADOW_PASS_ID 0
# define RENDER_SCENE_PASS_ID 1
2013-12-10 22:37:51 -05:00
uint32_t packUint32 ( uint8_t _x , uint8_t _y , uint8_t _z , uint8_t _w )
{
union
{
uint32_t ui32 ;
uint8_t arr [ 4 ] ;
} un ;
un . arr [ 0 ] = _x ;
un . arr [ 1 ] = _y ;
un . arr [ 2 ] = _z ;
un . arr [ 3 ] = _w ;
return un . ui32 ;
}
uint32_t packF4u ( float _x , float _y = 0.0f , float _z = 0.0f , float _w = 0.0f )
{
const uint8_t xx = uint8_t ( _x * 127.0f + 128.0f ) ;
const uint8_t yy = uint8_t ( _y * 127.0f + 128.0f ) ;
const uint8_t zz = uint8_t ( _z * 127.0f + 128.0f ) ;
const uint8_t ww = uint8_t ( _w * 127.0f + 128.0f ) ;
return packUint32 ( xx , yy , zz , ww ) ;
}
struct PosNormalVertex
{
float m_x ;
float m_y ;
float m_z ;
uint32_t m_normal ;
} ;
2014-08-17 20:20:15 -04:00
static PosNormalVertex s_hplaneVertices [ ] =
2013-12-10 22:37:51 -05:00
{
{ - 1.0f , 0.0f , 1.0f , packF4u ( 0.0f , 1.0f , 0.0f ) } ,
{ 1.0f , 0.0f , 1.0f , packF4u ( 0.0f , 1.0f , 0.0f ) } ,
{ - 1.0f , 0.0f , - 1.0f , packF4u ( 0.0f , 1.0f , 0.0f ) } ,
{ 1.0f , 0.0f , - 1.0f , packF4u ( 0.0f , 1.0f , 0.0f ) } ,
} ;
2014-08-17 20:20:15 -04:00
static const uint16_t s_planeIndices [ ] =
2013-12-10 22:37:51 -05:00
{
0 , 1 , 2 ,
1 , 3 , 2 ,
} ;
int _main_ ( int /*_argc*/ , char * * /*_argv*/ )
{
uint32_t width = 1280 ;
uint32_t height = 720 ;
uint32_t debug = BGFX_DEBUG_TEXT ;
uint32_t reset = BGFX_RESET_VSYNC ;
bgfx : : init ( ) ;
bgfx : : reset ( width , height , reset ) ;
2015-01-08 01:36:36 -05:00
bgfx : : RendererType : : Enum renderer = bgfx : : getRendererType ( ) ;
bool flipV = false
| | renderer = = bgfx : : RendererType : : OpenGL
| | renderer = = bgfx : : RendererType : : OpenGLES
;
2013-12-10 22:37:51 -05:00
// Enable debug text.
bgfx : : setDebug ( debug ) ;
// Uniforms.
2015-05-28 18:27:00 -04:00
bgfx : : UniformHandle u_shadowMap = bgfx : : createUniform ( " u_shadowMap " , bgfx : : UniformType : : Int1 ) ;
bgfx : : UniformHandle u_lightPos = bgfx : : createUniform ( " u_lightPos " , bgfx : : UniformType : : Vec4 ) ;
bgfx : : UniformHandle u_lightMtx = bgfx : : createUniform ( " u_lightMtx " , bgfx : : UniformType : : Mat4 ) ;
2013-12-10 22:37:51 -05:00
// Vertex declarations.
bgfx : : VertexDecl PosNormalDecl ;
2014-05-10 23:51:44 -04:00
PosNormalDecl . begin ( )
. add ( bgfx : : Attrib : : Position , 3 , bgfx : : AttribType : : Float )
. add ( bgfx : : Attrib : : Normal , 4 , bgfx : : AttribType : : Uint8 , true , true )
. end ( ) ;
2013-12-10 22:37:51 -05:00
// Meshes.
2015-01-08 01:36:36 -05:00
Mesh * bunny = meshLoad ( " meshes/bunny.bin " ) ;
Mesh * cube = meshLoad ( " meshes/cube.bin " ) ;
Mesh * hollowcube = meshLoad ( " meshes/hollowcube.bin " ) ;
bgfx : : VertexBufferHandle vbh = bgfx : : createVertexBuffer (
bgfx : : makeRef ( s_hplaneVertices , sizeof ( s_hplaneVertices ) )
, PosNormalDecl
) ;
bgfx : : IndexBufferHandle ibh = bgfx : : createIndexBuffer (
bgfx : : makeRef ( s_planeIndices , sizeof ( s_planeIndices ) )
) ;
2013-12-10 22:37:51 -05:00
// Render targets.
uint16_t shadowMapSize = 512 ;
2014-02-06 02:07:11 -05:00
2014-02-25 00:44:12 -05:00
// Get renderer capabilities info.
2014-02-25 00:47:00 -05:00
const bgfx : : Caps * caps = bgfx : : getCaps ( ) ;
2014-02-25 00:44:12 -05:00
// Shadow samplers are supported at least partially supported if texture
// compare less equal feature is supported.
2015-06-06 20:13:52 -04:00
bool shadowSamplerSupported = 0 ! = ( caps - > supported & BGFX_CAPS_TEXTURE_COMPARE_LEQUAL ) ;
2014-02-25 00:44:12 -05:00
bgfx : : ProgramHandle progShadow ;
bgfx : : ProgramHandle progMesh ;
2015-01-08 01:36:36 -05:00
bgfx : : TextureHandle shadowMapTexture ;
bgfx : : FrameBufferHandle shadowMapFB ;
2014-02-25 00:44:12 -05:00
if ( shadowSamplerSupported )
2014-02-06 02:07:11 -05:00
{
2014-02-25 00:44:12 -05:00
// Depth textures and shadow samplers are supported.
progShadow = loadProgram ( " vs_sms_shadow " , " fs_sms_shadow " ) ;
progMesh = loadProgram ( " vs_sms_mesh " , " fs_sms_mesh " ) ;
2015-01-08 01:36:36 -05:00
shadowMapTexture = bgfx : : createTexture2D ( shadowMapSize , shadowMapSize , 1 , bgfx : : TextureFormat : : D16 , BGFX_TEXTURE_COMPARE_LEQUAL ) ;
bgfx : : TextureHandle fbtextures [ ] = { shadowMapTexture } ;
shadowMapFB = bgfx : : createFrameBuffer ( BX_COUNTOF ( fbtextures ) , fbtextures , true ) ;
2014-02-25 00:44:12 -05:00
}
else
{
// Depth textures and shadow samplers are not supported. Use float
// depth packing into color buffer instead.
progShadow = loadProgram ( " vs_sms_shadow_pd " , " fs_sms_shadow_pd " ) ;
progMesh = loadProgram ( " vs_sms_mesh " , " fs_sms_mesh_pd " ) ;
2015-01-08 01:36:36 -05:00
shadowMapTexture = bgfx : : createTexture2D ( shadowMapSize , shadowMapSize , 1 , bgfx : : TextureFormat : : BGRA8 , BGFX_TEXTURE_RT ) ;
2014-02-25 00:44:12 -05:00
bgfx : : TextureHandle fbtextures [ ] =
{
2015-01-08 01:36:36 -05:00
shadowMapTexture ,
2014-02-25 00:44:12 -05:00
bgfx : : createTexture2D ( shadowMapSize , shadowMapSize , 1 , bgfx : : TextureFormat : : D16 , BGFX_TEXTURE_RT_BUFFER_ONLY ) ,
} ;
2015-01-08 01:36:36 -05:00
shadowMapFB = bgfx : : createFrameBuffer ( BX_COUNTOF ( fbtextures ) , fbtextures , true ) ;
2014-02-25 00:44:12 -05:00
}
2013-12-10 22:37:51 -05:00
2015-01-08 01:36:36 -05:00
MeshState * state [ 2 ] ;
state [ 0 ] = meshStateCreate ( ) ;
state [ 0 ] - > m_state = 0
| BGFX_STATE_RGB_WRITE
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_DEPTH_WRITE
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_CULL_CCW
| BGFX_STATE_MSAA
;
state [ 0 ] - > m_program = progShadow ;
state [ 0 ] - > m_viewId = RENDER_SHADOW_PASS_ID ;
state [ 0 ] - > m_numTextures = 0 ;
state [ 1 ] = meshStateCreate ( ) ;
state [ 1 ] - > m_state = 0
| BGFX_STATE_RGB_WRITE
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_DEPTH_WRITE
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_CULL_CCW
| BGFX_STATE_MSAA
;
state [ 1 ] - > m_program = progMesh ;
state [ 1 ] - > m_viewId = RENDER_SCENE_PASS_ID ;
state [ 1 ] - > m_numTextures = 1 ;
state [ 1 ] - > m_textures [ 0 ] . m_flags = UINT32_MAX ;
2015-06-06 19:57:43 -04:00
state [ 1 ] - > m_textures [ 0 ] . m_stage = 0 ;
2015-01-08 01:36:36 -05:00
state [ 1 ] - > m_textures [ 0 ] . m_sampler = u_shadowMap ;
state [ 1 ] - > m_textures [ 0 ] . m_texture = shadowMapTexture ;
2013-12-10 22:37:51 -05:00
// Set view and projection matrices.
float view [ 16 ] ;
float proj [ 16 ] ;
2015-04-04 22:10:35 -04:00
float eye [ 3 ] = { 0.0f , 30.0f , - 60.0f } ;
float at [ 3 ] = { 0.0f , 5.0f , 0.0f } ;
2014-05-26 22:31:37 -04:00
bx : : mtxLookAt ( view , eye , at ) ;
2013-12-10 22:37:51 -05:00
const float aspect = float ( int32_t ( width ) ) / float ( int32_t ( height ) ) ;
2015-01-08 01:36:36 -05:00
bx : : mtxProj ( proj , 60.0f , aspect , 0.1f , 1000.0f , flipV ) ;
2013-12-10 22:37:51 -05:00
// Time acumulators.
float timeAccumulatorLight = 0.0f ;
float timeAccumulatorScene = 0.0f ;
entry : : MouseState mouseState ;
while ( ! entry : : processEvents ( width , height , debug , reset , & mouseState ) )
{
// 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 ;
const float deltaTime = float ( frameTime / freq ) ;
// Update time accumulators.
timeAccumulatorLight + = deltaTime ;
timeAccumulatorScene + = deltaTime ;
// Use debug font to print information about this example.
bgfx : : dbgTextClear ( ) ;
bgfx : : dbgTextPrintf ( 0 , 1 , 0x4f , " bgfx/examples/15-shadowmaps-simple " ) ;
2014-02-25 00:44:12 -05:00
bgfx : : dbgTextPrintf ( 0 , 2 , 0x6f , " Description: Shadow maps example (technique: %s). " , shadowSamplerSupported ? " depth texture and shadow samplers " : " shadow depth packed into color texture " ) ;
2013-12-10 22:37:51 -05:00
bgfx : : dbgTextPrintf ( 0 , 3 , 0x0f , " Frame: % 7.3f[ms] " , double ( frameTime ) * toMs ) ;
// Setup lights.
float lightPos [ 4 ] ;
2015-03-29 14:47:32 -04:00
lightPos [ 0 ] = - cosf ( timeAccumulatorLight ) ;
2013-12-10 22:37:51 -05:00
lightPos [ 1 ] = - 1.0f ;
2015-03-29 14:47:32 -04:00
lightPos [ 2 ] = - sinf ( timeAccumulatorLight ) ;
2013-12-10 22:37:51 -05:00
lightPos [ 3 ] = 0.0f ;
bgfx : : setUniform ( u_lightPos , lightPos ) ;
// Setup instance matrices.
float mtxFloor [ 16 ] ;
2014-05-26 22:31:37 -04:00
bx : : mtxSRT ( mtxFloor
2014-02-22 16:36:31 -05:00
, 30.0f , 30.0f , 30.0f
, 0.0f , 0.0f , 0.0f
, 0.0f , 0.0f , 0.0f
2013-12-10 22:37:51 -05:00
) ;
float mtxBunny [ 16 ] ;
2014-05-26 22:31:37 -04:00
bx : : mtxSRT ( mtxBunny
2014-02-22 16:36:31 -05:00
, 5.0f , 5.0f , 5.0f
2014-10-25 21:07:51 -04:00
, 0.0f , bx : : pi - timeAccumulatorScene , 0.0f
2014-02-22 16:36:31 -05:00
, 15.0f , 5.0f , 0.0f
2013-12-10 22:37:51 -05:00
) ;
float mtxHollowcube [ 16 ] ;
2014-05-26 22:31:37 -04:00
bx : : mtxSRT ( mtxHollowcube
2014-02-22 16:36:31 -05:00
, 2.5f , 2.5f , 2.5f
, 0.0f , 1.56f - timeAccumulatorScene , 0.0f
, 0.0f , 10.0f , 0.0f
2013-12-10 22:37:51 -05:00
) ;
float mtxCube [ 16 ] ;
2014-05-26 22:31:37 -04:00
bx : : mtxSRT ( mtxCube
2014-02-22 16:36:31 -05:00
, 2.5f , 2.5f , 2.5f
, 0.0f , 1.56f - timeAccumulatorScene , 0.0f
, - 15.0f , 5.0f , 0.0f
2013-12-10 22:37:51 -05:00
) ;
// Define matrices.
float lightView [ 16 ] ;
float lightProj [ 16 ] ;
2015-04-04 22:10:35 -04:00
eye [ 0 ] = - lightPos [ 0 ] ;
2015-04-17 00:26:46 -04:00
eye [ 1 ] = - lightPos [ 1 ] ;
eye [ 2 ] = - lightPos [ 2 ] ;
2015-04-04 22:10:35 -04:00
at [ 0 ] = 0.0f ;
at [ 1 ] = 0.0f ;
at [ 2 ] = 0.0f ;
2014-05-26 22:31:37 -04:00
bx : : mtxLookAt ( lightView , eye , at ) ;
2013-12-10 22:37:51 -05:00
const float area = 30.0f ;
2014-05-26 22:31:37 -04:00
bx : : mtxOrtho ( lightProj , - area , area , - area , area , - 100.0f , 100.0f ) ;
2013-12-10 22:37:51 -05:00
2014-01-14 00:48:42 -05:00
bgfx : : setViewRect ( RENDER_SHADOW_PASS_ID , 0 , 0 , shadowMapSize , shadowMapSize ) ;
2015-01-08 01:36:36 -05:00
bgfx : : setViewFrameBuffer ( RENDER_SHADOW_PASS_ID , shadowMapFB ) ;
2014-01-14 00:48:42 -05:00
bgfx : : setViewTransform ( RENDER_SHADOW_PASS_ID , lightView , lightProj ) ;
2013-12-10 22:37:51 -05:00
2014-02-22 16:36:31 -05:00
bgfx : : setViewRect ( RENDER_SCENE_PASS_ID , 0 , 0 , width , height ) ;
bgfx : : setViewTransform ( RENDER_SCENE_PASS_ID , view , proj ) ;
2013-12-10 22:37:51 -05:00
2014-02-06 02:07:11 -05:00
// Clear backbuffer and shadowmap framebuffer at beginning.
2014-09-27 14:31:04 -04:00
bgfx : : setViewClear ( RENDER_SHADOW_PASS_ID
2015-01-11 00:39:45 -05:00
, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
2014-09-27 14:31:04 -04:00
, 0x303030ff , 1.0f , 0
) ;
bgfx : : setViewClear ( RENDER_SCENE_PASS_ID
2015-01-11 00:39:45 -05:00
, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
2014-02-22 16:36:31 -05:00
, 0x303030ff , 1.0f , 0
) ;
2013-12-10 22:37:51 -05:00
// Render.
2014-02-22 16:36:31 -05:00
float mtxShadow [ 16 ] ;
float lightMtx [ 16 ] ;
2013-12-10 22:37:51 -05:00
2015-01-08 01:36:36 -05:00
const float sy = flipV ? 0.5f : - 0.5f ;
2014-02-22 16:36:31 -05:00
const float mtxCrop [ 16 ] =
{
0.5f , 0.0f , 0.0f , 0.0f ,
0.0f , sy , 0.0f , 0.0f ,
0.0f , 0.0f , 0.5f , 0.0f ,
0.5f , 0.5f , 0.5f , 1.0f ,
} ;
2013-12-10 22:37:51 -05:00
2014-02-22 16:36:31 -05:00
float mtxTmp [ 16 ] ;
2015-01-08 01:36:36 -05:00
bx : : mtxMul ( mtxTmp , lightProj , mtxCrop ) ;
2014-05-26 22:31:37 -04:00
bx : : mtxMul ( mtxShadow , lightView , mtxTmp ) ;
2014-02-22 16:36:31 -05:00
// Floor.
2014-05-26 22:31:37 -04:00
bx : : mtxMul ( lightMtx , mtxFloor , mtxShadow ) ;
2015-01-08 01:36:36 -05:00
uint32_t cached = bgfx : : setTransform ( mtxFloor ) ;
for ( uint32_t pass = 0 ; pass < 2 ; + + pass )
{
const MeshState & st = * state [ pass ] ;
bgfx : : setTransform ( cached ) ;
for ( uint8_t tex = 0 ; tex < st . m_numTextures ; + + tex )
{
const MeshState : : Texture & texture = st . m_textures [ tex ] ;
bgfx : : setTexture ( texture . m_stage
, texture . m_sampler
, texture . m_texture
, texture . m_flags
) ;
}
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
bgfx : : setIndexBuffer ( ibh ) ;
bgfx : : setVertexBuffer ( vbh ) ;
bgfx : : setState ( st . m_state ) ;
2015-07-22 21:05:11 -04:00
bgfx : : submit ( st . m_viewId , st . m_program ) ;
2015-01-08 01:36:36 -05:00
}
2014-02-22 16:36:31 -05:00
// Bunny.
2014-05-26 22:31:37 -04:00
bx : : mtxMul ( lightMtx , mtxBunny , mtxShadow ) ;
2014-02-22 16:36:31 -05:00
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
2015-01-08 01:36:36 -05:00
meshSubmit ( bunny , & state [ 0 ] , 1 , mtxBunny ) ;
2015-08-07 13:37:02 -04:00
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
2015-01-08 01:36:36 -05:00
meshSubmit ( bunny , & state [ 1 ] , 1 , mtxBunny ) ;
2014-02-22 16:36:31 -05:00
// Hollow cube.
2014-05-26 22:31:37 -04:00
bx : : mtxMul ( lightMtx , mtxHollowcube , mtxShadow ) ;
2014-02-22 16:36:31 -05:00
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
2015-01-08 01:36:36 -05:00
meshSubmit ( hollowcube , & state [ 0 ] , 1 , mtxHollowcube ) ;
2015-08-07 13:37:02 -04:00
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
2015-01-08 01:36:36 -05:00
meshSubmit ( hollowcube , & state [ 1 ] , 1 , mtxHollowcube ) ;
2014-02-22 16:36:31 -05:00
// Cube.
2014-05-26 22:31:37 -04:00
bx : : mtxMul ( lightMtx , mtxCube , mtxShadow ) ;
2014-02-22 16:36:31 -05:00
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
2015-01-08 01:36:36 -05:00
meshSubmit ( cube , & state [ 0 ] , 1 , mtxCube ) ;
2015-08-07 13:37:02 -04:00
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
2015-01-08 01:36:36 -05:00
meshSubmit ( cube , & state [ 1 ] , 1 , mtxCube ) ;
2013-12-10 22:37:51 -05:00
// Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.
bgfx : : frame ( ) ;
}
2015-01-08 01:36:36 -05:00
meshUnload ( bunny ) ;
meshUnload ( cube ) ;
meshUnload ( hollowcube ) ;
meshStateDestroy ( state [ 0 ] ) ;
meshStateDestroy ( state [ 1 ] ) ;
bgfx : : destroyVertexBuffer ( vbh ) ;
bgfx : : destroyIndexBuffer ( ibh ) ;
2013-12-10 22:37:51 -05:00
2014-02-25 00:44:12 -05:00
bgfx : : destroyProgram ( progShadow ) ;
bgfx : : destroyProgram ( progMesh ) ;
2013-12-10 22:37:51 -05:00
2015-01-08 01:36:36 -05:00
bgfx : : destroyFrameBuffer ( shadowMapFB ) ;
2013-12-10 22:37:51 -05:00
bgfx : : destroyUniform ( u_shadowMap ) ;
bgfx : : destroyUniform ( u_lightPos ) ;
bgfx : : destroyUniform ( u_lightMtx ) ;
// Shutdown bgfx.
bgfx : : shutdown ( ) ;
return 0 ;
}