2013-01-06 17:53:45 -08:00
/*
2014-02-10 22:07:04 -08:00
* Copyright 2011 - 2014 Branimir Karadzic . All rights reserved .
2013-01-06 17:53:45 -08:00
* License : http : //www.opensource.org/licenses/BSD-2-Clause
*/
2013-05-23 22:07:54 -07:00
# include "common.h"
2013-05-18 22:12:40 -07:00
2013-01-06 17:53:45 -08:00
# include <bgfx.h>
# include <bx/timer.h>
2013-01-07 22:01:07 -08:00
# include <bx/uint32_t.h>
2013-05-23 22:07:54 -07:00
# include "fpumath.h"
# include "packrect.h"
2013-01-06 17:53:45 -08:00
# include <stdio.h>
# include <string.h>
2013-03-02 21:35:09 -08:00
# include <list>
2013-01-06 17:53:45 -08:00
struct PosColorVertex
{
float m_x ;
float m_y ;
float m_z ;
float m_u ;
float m_v ;
float m_w ;
} ;
static bgfx : : VertexDecl s_PosTexcoordDecl ;
static PosColorVertex s_cubeVertices [ 24 ] =
{
{ - 1.0f , 1.0f , 1.0f , - 1.0f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f , 1.0f , 1.0f } ,
{ - 1.0f , - 1.0f , 1.0f , - 1.0f , - 1.0f , 1.0f } ,
{ 1.0f , - 1.0f , 1.0f , 1.0f , - 1.0f , 1.0f } ,
{ - 1.0f , 1.0f , - 1.0f , - 1.0f , 1.0f , - 1.0f } ,
{ 1.0f , 1.0f , - 1.0f , 1.0f , 1.0f , - 1.0f } ,
{ - 1.0f , - 1.0f , - 1.0f , - 1.0f , - 1.0f , - 1.0f } ,
{ 1.0f , - 1.0f , - 1.0f , 1.0f , - 1.0f , - 1.0f } ,
{ - 1.0f , 1.0f , 1.0f , - 1.0f , 1.0f , 1.0f } ,
{ - 1.0f , 1.0f , - 1.0f , - 1.0f , 1.0f , - 1.0f } ,
{ - 1.0f , - 1.0f , 1.0f , - 1.0f , - 1.0f , 1.0f } ,
{ - 1.0f , - 1.0f , - 1.0f , - 1.0f , - 1.0f , - 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f , 1.0f , 1.0f } ,
{ 1.0f , - 1.0f , 1.0f , 1.0f , - 1.0f , 1.0f } ,
{ 1.0f , 1.0f , - 1.0f , 1.0f , 1.0f , - 1.0f } ,
{ 1.0f , - 1.0f , - 1.0f , 1.0f , - 1.0f , - 1.0f } ,
{ - 1.0f , 1.0f , 1.0f , - 1.0f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f , 1.0f , 1.0f , 1.0f } ,
{ - 1.0f , 1.0f , - 1.0f , - 1.0f , 1.0f , - 1.0f } ,
{ 1.0f , 1.0f , - 1.0f , 1.0f , 1.0f , - 1.0f } ,
{ - 1.0f , - 1.0f , 1.0f , - 1.0f , - 1.0f , 1.0f } ,
{ - 1.0f , - 1.0f , - 1.0f , - 1.0f , - 1.0f , - 1.0f } ,
{ 1.0f , - 1.0f , 1.0f , 1.0f , - 1.0f , 1.0f } ,
{ 1.0f , - 1.0f , - 1.0f , 1.0f , - 1.0f , - 1.0f } ,
} ;
static const uint16_t s_cubeIndices [ 36 ] =
{
2013-02-21 22:05:33 -08:00
0 , 1 , 2 , // 0
1 , 3 , 2 ,
4 , 6 , 5 , // 2
5 , 6 , 7 ,
8 , 10 , 9 , // 4
9 , 10 , 11 ,
12 , 14 , 13 , // 6
14 , 15 , 13 ,
16 , 18 , 17 , // 8
18 , 19 , 17 ,
20 , 22 , 21 , // 10
21 , 22 , 23 ,
2013-01-06 17:53:45 -08:00
} ;
static const char * s_shaderPath = NULL ;
static void shaderFilePath ( char * _out , const char * _name )
{
strcpy ( _out , s_shaderPath ) ;
strcat ( _out , _name ) ;
strcat ( _out , " .bin " ) ;
}
long int fsize ( FILE * _file )
{
long int pos = ftell ( _file ) ;
fseek ( _file , 0L , SEEK_END ) ;
long int size = ftell ( _file ) ;
fseek ( _file , pos , SEEK_SET ) ;
return size ;
}
static const bgfx : : Memory * load ( const char * _filePath )
{
FILE * file = fopen ( _filePath , " rb " ) ;
if ( NULL ! = file )
{
uint32_t size = ( uint32_t ) fsize ( file ) ;
const bgfx : : Memory * mem = bgfx : : alloc ( size + 1 ) ;
size_t ignore = fread ( mem - > data , 1 , size , file ) ;
BX_UNUSED ( ignore ) ;
fclose ( file ) ;
mem - > data [ mem - > size - 1 ] = ' \0 ' ;
return mem ;
}
return NULL ;
}
static const bgfx : : Memory * loadShader ( const char * _name )
{
char filePath [ 512 ] ;
shaderFilePath ( filePath , _name ) ;
return load ( filePath ) ;
}
2013-09-09 23:17:17 -07:00
static bgfx : : ProgramHandle loadProgram ( const char * _vshName , const char * _fshName )
{
const bgfx : : Memory * mem ;
mem = loadShader ( _vshName ) ;
bgfx : : VertexShaderHandle vsh = bgfx : : createVertexShader ( mem ) ;
mem = loadShader ( _fshName ) ;
bgfx : : FragmentShaderHandle fsh = bgfx : : createFragmentShader ( mem ) ;
// Create program from shaders.
bgfx : : ProgramHandle program = bgfx : : createProgram ( vsh , fsh ) ;
// We can destroy vertex and fragment shader here since
// their reference is kept inside bgfx after calling createProgram.
// Vertex and fragment shader will be destroyed once program is
// destroyed.
bgfx : : destroyVertexShader ( vsh ) ;
bgfx : : destroyFragmentShader ( fsh ) ;
return program ;
}
static const bgfx : : Memory * loadTexture ( const char * _name )
{
char filePath [ 512 ] ;
strcpy ( filePath , " textures/ " ) ;
strcat ( filePath , _name ) ;
return load ( filePath ) ;
}
2013-09-08 23:03:14 -07:00
static void updateTextureCubeRectBgra8 ( bgfx : : TextureHandle _handle , uint8_t _side , uint32_t _x , uint32_t _y , uint32_t _width , uint32_t _height , uint8_t _r , uint8_t _g , uint8_t _b , uint8_t _a = 0xff )
{
bgfx : : TextureInfo ti ;
bgfx : : calcTextureSize ( ti , _width , _height , 1 , 1 , bgfx : : TextureFormat : : BGRA8 ) ;
const bgfx : : Memory * mem = bgfx : : alloc ( ti . storageSize ) ;
uint8_t * data = ( uint8_t * ) mem - > data ;
for ( uint32_t ii = 0 , num = ti . storageSize * 8 / ti . bitsPerPixel ; ii < num ; + + ii )
{
data [ 0 ] = _b ;
data [ 1 ] = _g ;
data [ 2 ] = _r ;
data [ 3 ] = _a ;
data + = 4 ;
}
bgfx : : updateTextureCube ( _handle , _side , 0 , _x , _y , _width , _height , mem ) ;
}
2013-03-25 21:13:54 -07:00
int _main_ ( int /*_argc*/ , char * * /*_argv*/ )
2013-01-06 17:53:45 -08:00
{
2013-02-21 21:07:31 -08:00
uint32_t width = 1280 ;
uint32_t height = 720 ;
uint32_t debug = BGFX_DEBUG_TEXT ;
2013-04-27 18:47:18 -07:00
uint32_t reset = BGFX_RESET_VSYNC ;
2013-02-21 21:07:31 -08:00
bgfx : : init ( ) ;
2013-05-08 22:57:54 -07:00
bgfx : : reset ( width , height , reset ) ;
2013-02-21 21:07:31 -08:00
// Enable debug text.
bgfx : : setDebug ( debug ) ;
2013-01-06 17:53:45 -08:00
// Set view 0 clear state.
bgfx : : setViewClear ( 0
, BGFX_CLEAR_COLOR_BIT | BGFX_CLEAR_DEPTH_BIT
, 0x303030ff
, 1.0f
, 0
) ;
// Setup root path for binary shaders. Shader binaries are different
// for each renderer.
switch ( bgfx : : getRendererType ( ) )
{
default :
case bgfx : : RendererType : : Direct3D9 :
s_shaderPath = " shaders/dx9/ " ;
break ;
case bgfx : : RendererType : : Direct3D11 :
s_shaderPath = " shaders/dx11/ " ;
break ;
case bgfx : : RendererType : : OpenGL :
s_shaderPath = " shaders/glsl/ " ;
break ;
case bgfx : : RendererType : : OpenGLES2 :
case bgfx : : RendererType : : OpenGLES3 :
s_shaderPath = " shaders/gles/ " ;
break ;
}
// Create vertex stream declaration.
s_PosTexcoordDecl . begin ( ) ;
s_PosTexcoordDecl . add ( bgfx : : Attrib : : Position , 3 , bgfx : : AttribType : : Float ) ;
s_PosTexcoordDecl . add ( bgfx : : Attrib : : TexCoord0 , 3 , bgfx : : AttribType : : Float ) ;
s_PosTexcoordDecl . end ( ) ;
2013-09-09 23:17:17 -07:00
bgfx : : TextureHandle textures [ ] =
{
2013-11-17 20:57:38 -08:00
bgfx : : createTexture ( loadTexture ( " texture_compression_bc1.dds " ) ) ,
bgfx : : createTexture ( loadTexture ( " texture_compression_bc2.dds " ) ) ,
bgfx : : createTexture ( loadTexture ( " texture_compression_bc3.dds " ) ) ,
bgfx : : createTexture ( loadTexture ( " texture_compression_etc1.ktx " ) ) ,
bgfx : : createTexture ( loadTexture ( " texture_compression_etc2.ktx " ) ) ,
bgfx : : createTexture ( loadTexture ( " texture_compression_ptc12.pvr " ) ) ,
bgfx : : createTexture ( loadTexture ( " texture_compression_ptc14.pvr " ) ) ,
bgfx : : createTexture ( loadTexture ( " texture_compression_ptc22.pvr " ) ) ,
bgfx : : createTexture ( loadTexture ( " texture_compression_ptc24.pvr " ) ) ,
2013-09-09 23:17:17 -07:00
} ;
2013-11-17 20:57:38 -08:00
const bgfx : : Memory * mem ;
2013-01-06 17:53:45 -08:00
// Create static vertex buffer.
mem = bgfx : : makeRef ( s_cubeVertices , sizeof ( s_cubeVertices ) ) ;
bgfx : : VertexBufferHandle vbh = bgfx : : createVertexBuffer ( mem , s_PosTexcoordDecl ) ;
// Create static index buffer.
mem = bgfx : : makeRef ( s_cubeIndices , sizeof ( s_cubeIndices ) ) ;
bgfx : : IndexBufferHandle ibh = bgfx : : createIndexBuffer ( mem ) ;
// Create texture sampler uniforms.
bgfx : : UniformHandle u_texCube = bgfx : : createUniform ( " u_texCube " , bgfx : : UniformType : : Uniform1iv ) ;
2013-09-09 23:17:17 -07:00
bgfx : : UniformHandle u_texColor = bgfx : : createUniform ( " u_texColor " , bgfx : : UniformType : : Uniform1iv ) ;
2013-01-06 17:53:45 -08:00
2013-09-09 23:17:17 -07:00
bgfx : : ProgramHandle program = loadProgram ( " vs_update " , " fs_update " ) ;
bgfx : : ProgramHandle programCmp = loadProgram ( " vs_update " , " fs_update_cmp " ) ;
2013-01-06 17:53:45 -08:00
2013-03-02 21:35:09 -08:00
const uint32_t textureSide = 2048 ;
2013-01-06 17:53:45 -08:00
2013-11-08 22:10:31 -08:00
bgfx : : TextureHandle textureCube = bgfx : : createTextureCube ( textureSide , 1
, bgfx : : TextureFormat : : BGRA8
, BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT
) ;
const uint32_t texture2dSize = 256 ;
bgfx : : TextureHandle texture2d = bgfx : : createTexture2D ( texture2dSize , texture2dSize , 1
, bgfx : : TextureFormat : : BGRA8
, BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT
) ;
uint8_t * texture2dData = ( uint8_t * ) malloc ( texture2dSize * texture2dSize * 4 ) ;
2013-01-06 17:53:45 -08:00
uint8_t rr = rand ( ) % 255 ;
uint8_t gg = rand ( ) % 255 ;
uint8_t bb = rand ( ) % 255 ;
int64_t updateTime = 0 ;
2013-03-02 21:35:09 -08:00
RectPackCubeT < 256 > cube ( textureSide ) ;
uint32_t hit = 0 ;
uint32_t miss = 0 ;
std : : list < PackCube > quads ;
2013-04-27 12:43:18 -07:00
int64_t timeOffset = bx : : getHPCounter ( ) ;
2013-08-07 21:45:56 -07:00
while ( ! entry : : processEvents ( width , height , debug , reset ) )
2013-02-21 21:07:31 -08:00
{
2013-09-09 23:17:17 -07:00
// Set view 0 and 1 viewport.
bgfx : : setViewRectMask ( 0x3 , 0 , 0 , width , height ) ;
2013-02-21 21:07:31 -08:00
2013-01-06 17:53:45 -08:00
// This dummy draw call is here to make sure that view 0 is cleared
// if no other draw calls are submitted to view 0.
bgfx : : submit ( 0 ) ;
int64_t now = bx : : getHPCounter ( ) ;
static int64_t last = now ;
const int64_t frameTime = now - last ;
last = now ;
const int64_t freq = bx : : getHPFrequency ( ) ;
const double toMs = 1000.0 / double ( freq ) ;
2013-04-27 12:43:18 -07:00
float time = ( float ) ( ( now - timeOffset ) / double ( bx : : getHPFrequency ( ) ) ) ;
2013-01-06 17:53:45 -08:00
// Use debug font to print information about this example.
bgfx : : dbgTextClear ( ) ;
bgfx : : dbgTextPrintf ( 0 , 1 , 0x4f , " bgfx/examples/08-update " ) ;
bgfx : : dbgTextPrintf ( 0 , 2 , 0x6f , " Description: Updating textures. " ) ;
bgfx : : dbgTextPrintf ( 0 , 3 , 0x0f , " Frame: % 7.3f[ms] " , double ( frameTime ) * toMs ) ;
if ( now > updateTime )
{
2013-03-02 21:35:09 -08:00
PackCube face ;
2013-01-06 17:53:45 -08:00
2013-03-02 21:35:09 -08:00
uint32_t bw = bx : : uint16_max ( 1 , rand ( ) % ( textureSide / 4 ) ) ;
uint32_t bh = bx : : uint16_max ( 1 , rand ( ) % ( textureSide / 4 ) ) ;
2013-01-06 17:53:45 -08:00
2013-03-02 21:35:09 -08:00
if ( cube . find ( bw , bh , face ) )
2013-01-06 17:53:45 -08:00
{
2013-03-02 21:35:09 -08:00
quads . push_back ( face ) ;
+ + hit ;
const Pack2D & rect = face . m_rect ;
2013-09-08 23:14:34 -07:00
updateTextureCubeRectBgra8 ( textureCube , face . m_side , rect . m_x , rect . m_y , rect . m_width , rect . m_height , rr , gg , bb ) ;
2013-01-06 17:53:45 -08:00
2013-03-02 21:35:09 -08:00
rr = rand ( ) % 255 ;
gg = rand ( ) % 255 ;
bb = rand ( ) % 255 ;
}
else
{
+ + miss ;
2013-01-06 17:53:45 -08:00
2013-03-02 21:35:09 -08:00
for ( uint32_t ii = 0 , num = bx : : uint32_min ( 10 , ( uint32_t ) quads . size ( ) ) ; ii < num ; + + ii )
{
const PackCube & face = quads . front ( ) ;
cube . clear ( face ) ;
quads . pop_front ( ) ;
2013-01-06 17:53:45 -08:00
}
}
2013-11-08 22:10:31 -08:00
{
// Fill rect.
const uint32_t pitch = texture2dSize * 4 ;
const uint16_t tw = rand ( ) % texture2dSize ;
const uint16_t th = rand ( ) % texture2dSize ;
const uint16_t tx = rand ( ) % ( texture2dSize - tw ) ;
const uint16_t ty = rand ( ) % ( texture2dSize - th ) ;
uint8_t * dst = & texture2dData [ ( ty * texture2dSize + tx ) * 4 ] ;
uint8_t * next = dst + pitch ;
// Using makeRef to pass texture memory without copying.
const bgfx : : Memory * mem = bgfx : : makeRef ( dst , tw * th * 4 ) ;
for ( uint32_t yy = 0 ; yy < th ; + + yy , dst = next , next + = pitch )
{
for ( uint32_t xx = 0 ; xx < tw ; + + xx , dst + = 4 )
{
dst [ 0 ] = bb ;
dst [ 1 ] = gg ;
dst [ 2 ] = rr ;
dst [ 3 ] = 255 ;
}
}
// Pitch here makes possible to pass data from source to destination
// without need for textures and allocated memory to be the same size.
bgfx : : updateTexture2D ( texture2d , 0 , tx , ty , tw , th , mem , pitch ) ;
}
2013-01-06 17:53:45 -08:00
}
2013-03-02 21:35:09 -08:00
bgfx : : dbgTextPrintf ( 0 , 4 , 0x0f , " hit: %d, miss %d " , hit , miss ) ;
2013-01-06 17:53:45 -08:00
float at [ 3 ] = { 0.0f , 0.0f , 0.0f } ;
float eye [ 3 ] = { 0.0f , 0.0f , - 5.0f } ;
float view [ 16 ] ;
float proj [ 16 ] ;
mtxLookAt ( view , eye , at ) ;
2013-07-22 21:24:20 -07:00
mtxProj ( proj , 60.0f , float ( width ) / float ( height ) , 0.1f , 100.0f ) ;
2013-01-06 17:53:45 -08:00
// Set view and projection matrix for view 0.
bgfx : : setViewTransform ( 0 , view , proj ) ;
float mtx [ 16 ] ;
mtxRotateXY ( mtx , time , time * 0.37f ) ;
// Set model matrix for rendering.
bgfx : : setTransform ( mtx ) ;
// Set vertex and fragment shaders.
bgfx : : setProgram ( program ) ;
// Set vertex and index buffer.
bgfx : : setVertexBuffer ( vbh ) ;
bgfx : : setIndexBuffer ( ibh ) ;
// Bind texture.
bgfx : : setTexture ( 0 , u_texCube , textureCube ) ;
// Set render states.
2013-02-21 22:05:33 -08:00
bgfx : : setState ( BGFX_STATE_DEFAULT ) ;
2013-01-06 17:53:45 -08:00
// Submit primitive for rendering to view 0.
bgfx : : submit ( 0 ) ;
2013-09-09 23:17:17 -07:00
// Set view and projection matrix for view 1.
const float aspectRatio = float ( height ) / float ( width ) ;
const float size = 10.0f ;
mtxOrtho ( proj , - size , size , size * aspectRatio , - size * aspectRatio , 0.0f , 1000.0f ) ;
bgfx : : setViewTransform ( 1 , NULL , proj ) ;
2013-11-08 22:10:31 -08:00
mtxTranslate ( mtx , - 8.0f - BX_COUNTOF ( textures ) * 0.1f * 0.5f , 1.9f , 0.0f ) ;
// Set model matrix for rendering.
bgfx : : setTransform ( mtx ) ;
// Set vertex and fragment shaders.
bgfx : : setProgram ( programCmp ) ;
// Set vertex and index buffer.
bgfx : : setVertexBuffer ( vbh ) ;
bgfx : : setIndexBuffer ( ibh ) ;
// Bind texture.
bgfx : : setTexture ( 0 , u_texColor , texture2d ) ;
// Set render states.
bgfx : : setState ( BGFX_STATE_DEFAULT ) ;
// Submit primitive for rendering to view 0.
bgfx : : submit ( 1 ) ;
2013-09-09 23:17:17 -07:00
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( textures ) ; + + ii )
{
mtxTranslate ( mtx , - 8.0f - BX_COUNTOF ( textures ) * 0.1f * 0.5f + ii * 2.1f , 4.0f , 0.0f ) ;
// Set model matrix for rendering.
bgfx : : setTransform ( mtx ) ;
// Set vertex and fragment shaders.
bgfx : : setProgram ( programCmp ) ;
// Set vertex and index buffer.
bgfx : : setVertexBuffer ( vbh ) ;
bgfx : : setIndexBuffer ( ibh ) ;
// Bind texture.
bgfx : : setTexture ( 0 , u_texColor , textures [ ii ] ) ;
// Set render states.
bgfx : : setState ( BGFX_STATE_DEFAULT ) ;
// Submit primitive for rendering to view 0.
bgfx : : submit ( 1 ) ;
}
2013-01-06 17:53:45 -08:00
// Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.
bgfx : : frame ( ) ;
}
2014-02-20 22:04:50 -08:00
// texture2dData is managed from main thread, and it's passed to renderer
// just as MemoryRef. At this point render might be using it. We must wait
// previous frame to finish before we can free it.
bgfx : : frame ( ) ;
2013-01-06 17:53:45 -08:00
// Cleanup.
2013-11-08 22:10:31 -08:00
free ( texture2dData ) ;
2013-11-17 20:57:38 -08:00
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( textures ) ; + + ii )
{
bgfx : : destroyTexture ( textures [ ii ] ) ;
}
2013-11-08 22:10:31 -08:00
bgfx : : destroyTexture ( texture2d ) ;
bgfx : : destroyTexture ( textureCube ) ;
2013-01-06 17:53:45 -08:00
bgfx : : destroyIndexBuffer ( ibh ) ;
bgfx : : destroyVertexBuffer ( vbh ) ;
2013-09-09 23:17:17 -07:00
bgfx : : destroyProgram ( programCmp ) ;
2013-01-06 17:53:45 -08:00
bgfx : : destroyProgram ( program ) ;
2013-09-09 23:17:17 -07:00
bgfx : : destroyUniform ( u_texColor ) ;
2013-01-28 22:08:16 -08:00
bgfx : : destroyUniform ( u_texCube ) ;
2013-01-06 17:53:45 -08:00
// Shutdown bgfx.
bgfx : : shutdown ( ) ;
return 0 ;
}