2013-12-11 07:37:51 +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-12-11 07:37:51 +04:00
*/
# include <string>
# include <vector>
# include <algorithm>
# include "common.h"
2015-09-19 06:16:24 +03:00
# include <bgfx/bgfx.h>
2013-12-11 07:37:51 +04:00
# include <bx/timer.h>
# include <bx/readerwriter.h>
2014-05-27 06:31:37 +04:00
# include <bx/fpumath.h>
2013-12-11 07:37:51 +04:00
# include "entry/entry.h"
2015-01-08 09:36:36 +03:00
# include "bgfx_utils.h"
2013-12-11 07:37:51 +04:00
2014-01-14 09:48:42 +04:00
# define RENDER_SHADOW_PASS_ID 0
# define RENDER_SCENE_PASS_ID 1
2013-12-11 07:37:51 +04: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-18 04:20:15 +04:00
static PosNormalVertex s_hplaneVertices [ ] =
2013-12-11 07:37:51 +04: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-18 04:20:15 +04:00
static const uint16_t s_planeIndices [ ] =
2013-12-11 07:37:51 +04:00
{
0 , 1 , 2 ,
1 , 3 , 2 ,
} ;
2015-10-24 06:52:22 +03:00
int _main_ ( int _argc , char * * _argv )
2013-12-11 07:37:51 +04:00
{
2015-10-24 06:52:22 +03:00
Args args ( _argc , _argv ) ;
2013-12-11 07:37:51 +04:00
uint32_t width = 1280 ;
uint32_t height = 720 ;
uint32_t debug = BGFX_DEBUG_TEXT ;
uint32_t reset = BGFX_RESET_VSYNC ;
2015-10-24 06:52:22 +03:00
bgfx : : init ( args . m_type , args . m_pciId ) ;
2013-12-11 07:37:51 +04:00
bgfx : : reset ( width , height , reset ) ;
2015-01-08 09:36:36 +03:00
bgfx : : RendererType : : Enum renderer = bgfx : : getRendererType ( ) ;
bool flipV = false
| | renderer = = bgfx : : RendererType : : OpenGL
| | renderer = = bgfx : : RendererType : : OpenGLES
;
2013-12-11 07:37:51 +04:00
// Enable debug text.
bgfx : : setDebug ( debug ) ;
// Uniforms.
2015-05-29 01:27:00 +03: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 ) ;
2016-01-18 10:05:40 +03:00
// When using GL clip space depth range [-1, 1] and packing depth into color buffer, we need to
// adjust the depth range to be [0, 1] for writing to the color buffer
bgfx : : UniformHandle u_depthScaleOffset = bgfx : : createUniform ( " u_depthScaleOffset " , bgfx : : UniformType : : Vec4 ) ;
const float depthScale = flipV ? 0.5f : 1.0f ;
const float depthOffset = flipV ? 0.5f : 0.0f ;
float depthScaleOffset [ 4 ] = { depthScale , depthOffset , 0.0f , 0.0f } ;
bgfx : : setUniform ( u_depthScaleOffset , depthScaleOffset ) ;
2013-12-11 07:37:51 +04:00
// Vertex declarations.
bgfx : : VertexDecl PosNormalDecl ;
2014-05-11 07: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-11 07:37:51 +04:00
// Meshes.
2015-01-08 09:36:36 +03: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-11 07:37:51 +04:00
// Render targets.
uint16_t shadowMapSize = 512 ;
2014-02-06 11:07:11 +04:00
2014-02-25 09:44:12 +04:00
// Get renderer capabilities info.
2014-02-25 09:47:00 +04:00
const bgfx : : Caps * caps = bgfx : : getCaps ( ) ;
2014-02-25 09:44:12 +04:00
// Shadow samplers are supported at least partially supported if texture
// compare less equal feature is supported.
2015-06-07 03:13:52 +03:00
bool shadowSamplerSupported = 0 ! = ( caps - > supported & BGFX_CAPS_TEXTURE_COMPARE_LEQUAL ) ;
2014-02-25 09:44:12 +04:00
bgfx : : ProgramHandle progShadow ;
bgfx : : ProgramHandle progMesh ;
2015-01-08 09:36:36 +03:00
bgfx : : TextureHandle shadowMapTexture ;
bgfx : : FrameBufferHandle shadowMapFB ;
2014-02-25 09:44:12 +04:00
if ( shadowSamplerSupported )
2014-02-06 11:07:11 +04:00
{
2014-02-25 09:44:12 +04: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-11-22 20:36:57 +03:00
shadowMapTexture = bgfx : : createTexture2D ( shadowMapSize , shadowMapSize , 1 , bgfx : : TextureFormat : : D16 , BGFX_TEXTURE_RT | BGFX_TEXTURE_COMPARE_LEQUAL ) ;
2015-01-08 09:36:36 +03:00
bgfx : : TextureHandle fbtextures [ ] = { shadowMapTexture } ;
shadowMapFB = bgfx : : createFrameBuffer ( BX_COUNTOF ( fbtextures ) , fbtextures , true ) ;
2014-02-25 09:44:12 +04: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 09:36:36 +03:00
shadowMapTexture = bgfx : : createTexture2D ( shadowMapSize , shadowMapSize , 1 , bgfx : : TextureFormat : : BGRA8 , BGFX_TEXTURE_RT ) ;
2014-02-25 09:44:12 +04:00
bgfx : : TextureHandle fbtextures [ ] =
{
2015-01-08 09:36:36 +03:00
shadowMapTexture ,
2016-01-13 04:11:16 +03:00
bgfx : : createTexture2D ( shadowMapSize , shadowMapSize , 1 , bgfx : : TextureFormat : : D16 , BGFX_TEXTURE_RT_WRITE_ONLY ) ,
2014-02-25 09:44:12 +04:00
} ;
2015-01-08 09:36:36 +03:00
shadowMapFB = bgfx : : createFrameBuffer ( BX_COUNTOF ( fbtextures ) , fbtextures , true ) ;
2014-02-25 09:44:12 +04:00
}
2013-12-11 07:37:51 +04:00
2015-01-08 09:36:36 +03: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-07 02:57:43 +03:00
state [ 1 ] - > m_textures [ 0 ] . m_stage = 0 ;
2015-01-08 09:36:36 +03:00
state [ 1 ] - > m_textures [ 0 ] . m_sampler = u_shadowMap ;
state [ 1 ] - > m_textures [ 0 ] . m_texture = shadowMapTexture ;
2013-12-11 07:37:51 +04:00
// Set view and projection matrices.
float view [ 16 ] ;
float proj [ 16 ] ;
2015-04-05 05:10:35 +03:00
float eye [ 3 ] = { 0.0f , 30.0f , - 60.0f } ;
float at [ 3 ] = { 0.0f , 5.0f , 0.0f } ;
2014-05-27 06:31:37 +04:00
bx : : mtxLookAt ( view , eye , at ) ;
2013-12-11 07:37:51 +04:00
const float aspect = float ( int32_t ( width ) ) / float ( int32_t ( height ) ) ;
2015-01-08 09:36:36 +03:00
bx : : mtxProj ( proj , 60.0f , aspect , 0.1f , 1000.0f , flipV ) ;
2013-12-11 07:37:51 +04: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 09:44:12 +04: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-11 07:37:51 +04:00
bgfx : : dbgTextPrintf ( 0 , 3 , 0x0f , " Frame: % 7.3f[ms] " , double ( frameTime ) * toMs ) ;
// Setup lights.
float lightPos [ 4 ] ;
2015-03-29 21:47:32 +03:00
lightPos [ 0 ] = - cosf ( timeAccumulatorLight ) ;
2013-12-11 07:37:51 +04:00
lightPos [ 1 ] = - 1.0f ;
2015-03-29 21:47:32 +03:00
lightPos [ 2 ] = - sinf ( timeAccumulatorLight ) ;
2013-12-11 07:37:51 +04:00
lightPos [ 3 ] = 0.0f ;
bgfx : : setUniform ( u_lightPos , lightPos ) ;
// Setup instance matrices.
float mtxFloor [ 16 ] ;
2014-05-27 06:31:37 +04:00
bx : : mtxSRT ( mtxFloor
2014-02-23 01:36:31 +04:00
, 30.0f , 30.0f , 30.0f
, 0.0f , 0.0f , 0.0f
, 0.0f , 0.0f , 0.0f
2013-12-11 07:37:51 +04:00
) ;
float mtxBunny [ 16 ] ;
2014-05-27 06:31:37 +04:00
bx : : mtxSRT ( mtxBunny
2014-02-23 01:36:31 +04:00
, 5.0f , 5.0f , 5.0f
2014-10-26 04:07:51 +03:00
, 0.0f , bx : : pi - timeAccumulatorScene , 0.0f
2014-02-23 01:36:31 +04:00
, 15.0f , 5.0f , 0.0f
2013-12-11 07:37:51 +04:00
) ;
float mtxHollowcube [ 16 ] ;
2014-05-27 06:31:37 +04:00
bx : : mtxSRT ( mtxHollowcube
2014-02-23 01:36:31 +04:00
, 2.5f , 2.5f , 2.5f
, 0.0f , 1.56f - timeAccumulatorScene , 0.0f
, 0.0f , 10.0f , 0.0f
2013-12-11 07:37:51 +04:00
) ;
float mtxCube [ 16 ] ;
2014-05-27 06:31:37 +04:00
bx : : mtxSRT ( mtxCube
2014-02-23 01:36:31 +04:00
, 2.5f , 2.5f , 2.5f
, 0.0f , 1.56f - timeAccumulatorScene , 0.0f
, - 15.0f , 5.0f , 0.0f
2013-12-11 07:37:51 +04:00
) ;
// Define matrices.
float lightView [ 16 ] ;
float lightProj [ 16 ] ;
2015-04-05 05:10:35 +03:00
eye [ 0 ] = - lightPos [ 0 ] ;
2015-04-17 07:26:46 +03:00
eye [ 1 ] = - lightPos [ 1 ] ;
eye [ 2 ] = - lightPos [ 2 ] ;
2015-04-05 05:10:35 +03:00
at [ 0 ] = 0.0f ;
at [ 1 ] = 0.0f ;
at [ 2 ] = 0.0f ;
2014-05-27 06:31:37 +04:00
bx : : mtxLookAt ( lightView , eye , at ) ;
2013-12-11 07:37:51 +04:00
const float area = 30.0f ;
2016-01-16 01:54:56 +03:00
bx : : mtxOrtho ( lightProj , - area , area , - area , area , - 100.0f , 100.0f , 0.0f , flipV ) ;
2013-12-11 07:37:51 +04:00
2014-01-14 09:48:42 +04:00
bgfx : : setViewRect ( RENDER_SHADOW_PASS_ID , 0 , 0 , shadowMapSize , shadowMapSize ) ;
2015-01-08 09:36:36 +03:00
bgfx : : setViewFrameBuffer ( RENDER_SHADOW_PASS_ID , shadowMapFB ) ;
2014-01-14 09:48:42 +04:00
bgfx : : setViewTransform ( RENDER_SHADOW_PASS_ID , lightView , lightProj ) ;
2013-12-11 07:37:51 +04:00
2014-02-23 01:36:31 +04:00
bgfx : : setViewRect ( RENDER_SCENE_PASS_ID , 0 , 0 , width , height ) ;
bgfx : : setViewTransform ( RENDER_SCENE_PASS_ID , view , proj ) ;
2013-12-11 07:37:51 +04:00
2014-02-06 11:07:11 +04:00
// Clear backbuffer and shadowmap framebuffer at beginning.
2014-09-27 22:31:04 +04:00
bgfx : : setViewClear ( RENDER_SHADOW_PASS_ID
2015-01-11 08:39:45 +03:00
, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
2014-09-27 22:31:04 +04:00
, 0x303030ff , 1.0f , 0
) ;
bgfx : : setViewClear ( RENDER_SCENE_PASS_ID
2015-01-11 08:39:45 +03:00
, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
2014-02-23 01:36:31 +04:00
, 0x303030ff , 1.0f , 0
) ;
2013-12-11 07:37:51 +04:00
// Render.
2014-02-23 01:36:31 +04:00
float mtxShadow [ 16 ] ;
float lightMtx [ 16 ] ;
2013-12-11 07:37:51 +04:00
2015-01-08 09:36:36 +03:00
const float sy = flipV ? 0.5f : - 0.5f ;
2014-02-23 01:36:31 +04:00
const float mtxCrop [ 16 ] =
{
0.5f , 0.0f , 0.0f , 0.0f ,
0.0f , sy , 0.0f , 0.0f ,
2016-01-18 10:05:40 +03:00
0.0f , 0.0f , depthScale , 0.0f ,
0.5f , 0.5f , depthOffset , 1.0f ,
2014-02-23 01:36:31 +04:00
} ;
2013-12-11 07:37:51 +04:00
2014-02-23 01:36:31 +04:00
float mtxTmp [ 16 ] ;
2015-01-08 09:36:36 +03:00
bx : : mtxMul ( mtxTmp , lightProj , mtxCrop ) ;
2014-05-27 06:31:37 +04:00
bx : : mtxMul ( mtxShadow , lightView , mtxTmp ) ;
2014-02-23 01:36:31 +04:00
// Floor.
2014-05-27 06:31:37 +04:00
bx : : mtxMul ( lightMtx , mtxFloor , mtxShadow ) ;
2015-01-08 09:36:36 +03: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-23 04:05:11 +03:00
bgfx : : submit ( st . m_viewId , st . m_program ) ;
2015-01-08 09:36:36 +03:00
}
2014-02-23 01:36:31 +04:00
// Bunny.
2014-05-27 06:31:37 +04:00
bx : : mtxMul ( lightMtx , mtxBunny , mtxShadow ) ;
2014-02-23 01:36:31 +04:00
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
2015-01-08 09:36:36 +03:00
meshSubmit ( bunny , & state [ 0 ] , 1 , mtxBunny ) ;
2015-08-07 20:37:02 +03:00
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
2015-01-08 09:36:36 +03:00
meshSubmit ( bunny , & state [ 1 ] , 1 , mtxBunny ) ;
2014-02-23 01:36:31 +04:00
// Hollow cube.
2014-05-27 06:31:37 +04:00
bx : : mtxMul ( lightMtx , mtxHollowcube , mtxShadow ) ;
2014-02-23 01:36:31 +04:00
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
2015-01-08 09:36:36 +03:00
meshSubmit ( hollowcube , & state [ 0 ] , 1 , mtxHollowcube ) ;
2015-08-07 20:37:02 +03:00
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
2015-01-08 09:36:36 +03:00
meshSubmit ( hollowcube , & state [ 1 ] , 1 , mtxHollowcube ) ;
2014-02-23 01:36:31 +04:00
// Cube.
2014-05-27 06:31:37 +04:00
bx : : mtxMul ( lightMtx , mtxCube , mtxShadow ) ;
2014-02-23 01:36:31 +04:00
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
2015-01-08 09:36:36 +03:00
meshSubmit ( cube , & state [ 0 ] , 1 , mtxCube ) ;
2015-08-07 20:37:02 +03:00
bgfx : : setUniform ( u_lightMtx , lightMtx ) ;
2015-01-08 09:36:36 +03:00
meshSubmit ( cube , & state [ 1 ] , 1 , mtxCube ) ;
2013-12-11 07:37:51 +04:00
// Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.
bgfx : : frame ( ) ;
}
2015-01-08 09:36:36 +03:00
meshUnload ( bunny ) ;
meshUnload ( cube ) ;
meshUnload ( hollowcube ) ;
meshStateDestroy ( state [ 0 ] ) ;
meshStateDestroy ( state [ 1 ] ) ;
bgfx : : destroyVertexBuffer ( vbh ) ;
bgfx : : destroyIndexBuffer ( ibh ) ;
2013-12-11 07:37:51 +04:00
2014-02-25 09:44:12 +04:00
bgfx : : destroyProgram ( progShadow ) ;
bgfx : : destroyProgram ( progMesh ) ;
2013-12-11 07:37:51 +04:00
2015-01-08 09:36:36 +03:00
bgfx : : destroyFrameBuffer ( shadowMapFB ) ;
2013-12-11 07:37:51 +04:00
bgfx : : destroyUniform ( u_shadowMap ) ;
bgfx : : destroyUniform ( u_lightPos ) ;
bgfx : : destroyUniform ( u_lightMtx ) ;
// Shutdown bgfx.
bgfx : : shutdown ( ) ;
return 0 ;
}