This commit is contained in:
bkaradzic 2013-10-18 23:05:33 -07:00
parent dcd0452d82
commit 49e14b2a54

View file

@ -15,6 +15,15 @@
#include <string> #include <string>
#include <vector> #include <vector>
#define RENDER_VIEWID_RANGE1_PASS_0 1
#define RENDER_VIEWID_RANGE1_PASS_1 2
#define RENDER_VIEWID_RANGE1_PASS_2 3
#define RENDER_VIEWID_RANGE1_PASS_3 4
#define RENDER_VIEWID_RANGE1_PASS_4 5
#define RENDER_VIEWID_RANGE1_PASS_5 6
#define RENDER_VIEWID_RANGE5_PASS_6 7
#define RENDER_VIEWID_RANGE1_PASS_7 13
uint32_t packUint32(uint8_t _x, uint8_t _y, uint8_t _z, uint8_t _w) uint32_t packUint32(uint8_t _x, uint8_t _y, uint8_t _z, uint8_t _w)
{ {
union union
@ -273,10 +282,11 @@ void mtxShadow(float* __restrict _result
, const float* __restrict _light , const float* __restrict _light
) )
{ {
float dot = _ground[0] * _light[0] + float dot = _ground[0] * _light[0]
_ground[1] * _light[1] + + _ground[1] * _light[1]
_ground[2] * _light[2] + + _ground[2] * _light[2]
_ground[3] * _light[3]; + _ground[3] * _light[3]
;
_result[ 0] = dot - _light[0] * _ground[0]; _result[ 0] = dot - _light[0] * _ground[0];
_result[ 1] = 0.0f - _light[1] * _ground[0]; _result[ 1] = 0.0f - _light[1] * _ground[0];
@ -322,10 +332,6 @@ void mtxBillboard(float* __restrict _result
_result[15] = 1.0f; _result[15] = 1.0f;
} }
//-------------------------------------------------
// Render state
//-------------------------------------------------
struct RenderState struct RenderState
{ {
enum Enum enum Enum
@ -934,26 +940,30 @@ int _main_(int /*_argc*/, char** /*_argv*/)
int64_t timeOffset = bx::getHPCounter(); int64_t timeOffset = bx::getHPCounter();
entry::MouseState mouseState; enum Scene
while (!entry::processEvents(viewState.m_width, viewState.m_height, debug, reset, &mouseState) )
{
//imgui
static float settings_numLights = 4.0f;
static float settings_reflectionValue = 0.8f;
static bool settings_updateLights = true;
static bool settings_updateScene = true;
static enum Scene
{ {
StencilReflectionScene = 0, StencilReflectionScene = 0,
ProjectionShadowsScene, ProjectionShadowsScene,
} scene = StencilReflectionScene; }
static std::string titles[3] = Scene scene = StencilReflectionScene;
float settings_numLights = 4.0f;
float settings_reflectionValue = 0.8f;
bool settings_updateLights = true;
bool settings_updateScene = true;
static const char* titles[3] =
{ {
"Stencil Reflection Scene", "Stencil Reflection Scene",
"Projection Shadows Scene", "Projection Shadows Scene",
}; };
entry::MouseState mouseState;
while (!entry::processEvents(viewState.m_width, viewState.m_height, debug, reset, &mouseState) )
{
//imgui
imguiBeginFrame(mouseState.m_mx imguiBeginFrame(mouseState.m_mx
, mouseState.m_my , mouseState.m_my
, (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0) , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0)
@ -966,13 +976,13 @@ int _main_(int /*_argc*/, char** /*_argv*/)
static int32_t scrollArea = 0; static int32_t scrollArea = 0;
imguiBeginScrollArea("Settings", viewState.m_width - 256 - 10, 10, 256, 215, &scrollArea); imguiBeginScrollArea("Settings", viewState.m_width - 256 - 10, 10, 256, 215, &scrollArea);
if (imguiCheck(titles[StencilReflectionScene].c_str(), StencilReflectionScene == scene)) if (imguiCheck(titles[StencilReflectionScene], StencilReflectionScene == scene) )
{ {
scene = StencilReflectionScene; scene = StencilReflectionScene;
settings_numLights = 4.0f; settings_numLights = 4.0f;
} }
if (imguiCheck(titles[ProjectionShadowsScene].c_str(), ProjectionShadowsScene == scene)) if (imguiCheck(titles[ProjectionShadowsScene], ProjectionShadowsScene == scene) )
{ {
scene = ProjectionShadowsScene; scene = ProjectionShadowsScene;
settings_numLights = 1.0f; settings_numLights = 1.0f;
@ -985,20 +995,27 @@ int _main_(int /*_argc*/, char** /*_argv*/)
imguiSlider("Reflection value", &settings_reflectionValue, 0.0f, 1.0f, 0.01f); imguiSlider("Reflection value", &settings_reflectionValue, 0.0f, 1.0f, 0.01f);
} }
if (imguiCheck("Update lights", settings_updateLights)) { settings_updateLights = !settings_updateLights; } if (imguiCheck("Update lights", settings_updateLights) )
if (imguiCheck("Update scene", settings_updateScene)) { settings_updateScene = !settings_updateScene; } {
settings_updateLights = !settings_updateLights;
}
if (imguiCheck("Update scene", settings_updateScene) )
{
settings_updateScene = !settings_updateScene;
}
imguiEndScrollArea(); imguiEndScrollArea();
imguiEndFrame(); imguiEndFrame();
//update settings // Update settings.
numLights = (uint8_t)settings_numLights; numLights = (uint8_t)settings_numLights;
params.m_ambientPass = 1.0f; params.m_ambientPass = 1.0f;
params.m_lightningPass = 1.0f; params.m_lightningPass = 1.0f;
params.m_lightCount = settings_numLights; params.m_lightCount = settings_numLights;
bgfx::setUniform(u_params, (const void*)&params); bgfx::setUniform(u_params, (const void*)&params);
//time // Time.
int64_t now = bx::getHPCounter(); int64_t now = bx::getHPCounter();
static int64_t last = now; static int64_t last = now;
const int64_t frameTime = now - last; const int64_t frameTime = now - last;
@ -1009,13 +1026,13 @@ int _main_(int /*_argc*/, char** /*_argv*/)
const float deltaTime = float(frameTime/freq); const float deltaTime = float(frameTime/freq);
bgfx::setUniform(u_time, &time); bgfx::setUniform(u_time, &time);
//use debug font to print information about this example. // Use debug font to print information about this example.
bgfx::dbgTextClear(); bgfx::dbgTextClear();
bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/13-stencil"); bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/13-stencil");
bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Stencil reflections and shadows."); bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Stencil reflections and shadows.");
bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs); bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
//set view and projection matrices // Set view and projection matrices.
const float aspect = float(viewState.m_width)/float(viewState.m_height); const float aspect = float(viewState.m_width)/float(viewState.m_height);
mtxProj(viewState.m_proj, 60.0f, aspect, 0.1f, 100.0f); mtxProj(viewState.m_proj, 60.0f, aspect, 0.1f, 100.0f);
float at[3] = { 0.0f, 5.0f, 0.0f }; float at[3] = { 0.0f, 5.0f, 0.0f };
@ -1039,7 +1056,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
for (uint8_t ii = 0; ii < numLights; ++ii) for (uint8_t ii = 0; ii < numLights; ++ii)
{ {
lightPosRadius[ii][0] = sin( (lightTimeAccumulator*(1.1f + ii*0.07f) + float(ii*M_PI_2)*1.07f ) )*25.0f; lightPosRadius[ii][0] = sin( (lightTimeAccumulator*(1.1f + ii*0.07f) + float(ii*M_PI_2)*1.07f ) )*25.0f;
lightPosRadius[ii][1] = 7.0f + (1.0f - cos( (lightTimeAccumulator*(1.2f + ii*0.29f) + float(ii*M_PI_2)*1.49f )))*5.0f; lightPosRadius[ii][1] = 7.0f + (1.0f - cos( (lightTimeAccumulator*(1.2f + ii*0.29f) + float(ii*M_PI_2)*1.49f ) ))*5.0f;
lightPosRadius[ii][2] = cos( (lightTimeAccumulator*(1.3f + ii*0.09f) + float(ii*M_PI_2)*1.79f ) )*20.0f; lightPosRadius[ii][2] = cos( (lightTimeAccumulator*(1.3f + ii*0.09f) + float(ii*M_PI_2)*1.79f ) )*20.0f;
lightPosRadius[ii][3] = radius; lightPosRadius[ii][3] = radius;
} }
@ -1131,43 +1148,28 @@ int _main_(int /*_argc*/, char** /*_argv*/)
color[2] = 1.0f; color[2] = 1.0f;
bgfx::setUniform(u_color, color); bgfx::setUniform(u_color, color);
#define RENDER_VIEWID_RANGE1_PASS_0 1
#define RENDER_VIEWID_RANGE1_PASS_1 2
#define RENDER_VIEWID_RANGE1_PASS_2 3
#define RENDER_VIEWID_RANGE1_PASS_3 4
#define RENDER_VIEWID_RANGE1_PASS_4 5
#define RENDER_VIEWID_RANGE1_PASS_5 6
#define RENDER_VIEWID_RANGE5_PASS_6 7
#define RENDER_VIEWID_RANGE1_PASS_7 13
switch (scene) switch (scene)
{ {
case StencilReflectionScene: case StencilReflectionScene:
{ {
/** // First pass - Draw plane.
* First pass
* Draw plane.
*/
//floor // Floor
hplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_0 hplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_0
, floorMtx , floorMtx
, programColorBlack , programColorBlack
, s_renderStates[RenderState::StencilReflection_CraftStencil] , s_renderStates[RenderState::StencilReflection_CraftStencil]
); );
/** // Second pass - Draw reflected objects.
* Second pass
* Draw reflected objects.
*/
//compute reflected mtx // Compute reflected matrix.
float reflectMtx[16]; float reflectMtx[16];
float plane_pos[3] = { 0.0f, 0.01f, 0.0f }; float plane_pos[3] = { 0.0f, 0.01f, 0.0f };
float normal[3] = { 0.0f, 1.0f, 0.0f }; float normal[3] = { 0.0f, 1.0f, 0.0f };
mtxReflected(reflectMtx, plane_pos, normal); mtxReflected(reflectMtx, plane_pos, normal);
//reflect lights // Reflect lights.
float reflectedLights[MAX_NUM_LIGHTS][4]; float reflectedLights[MAX_NUM_LIGHTS][4];
for (uint8_t ii = 0; ii < numLights; ++ii) for (uint8_t ii = 0; ii < numLights; ++ii)
{ {
@ -1176,7 +1178,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
} }
bgfx::setUniform(u_lightPosRadius, reflectedLights, numLights); bgfx::setUniform(u_lightPosRadius, reflectedLights, numLights);
//reflect and submit bunny // Reflect and submit bunny.
float mtxReflectedBunny[16]; float mtxReflectedBunny[16];
mtxMul(mtxReflectedBunny, bunnyMtx, reflectMtx); mtxMul(mtxReflectedBunny, bunnyMtx, reflectMtx);
bunnyMesh.submit(RENDER_VIEWID_RANGE1_PASS_1 bunnyMesh.submit(RENDER_VIEWID_RANGE1_PASS_1
@ -1185,7 +1187,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
, s_renderStates[RenderState::StencilReflection_DrawReflected] , s_renderStates[RenderState::StencilReflection_DrawReflected]
); );
//reflect and submit columns // Reflect and submit columns.
float mtxReflectedColumn[16]; float mtxReflectedColumn[16];
for (uint8_t ii = 0; ii < 4; ++ii) for (uint8_t ii = 0; ii < 4; ++ii)
{ {
@ -1197,13 +1199,10 @@ int _main_(int /*_argc*/, char** /*_argv*/)
); );
} }
//set lights back // Set lights back.
bgfx::setUniform(u_lightPosRadius, lightPosRadius, numLights); bgfx::setUniform(u_lightPosRadius, lightPosRadius, numLights);
/** // Third pass - Darken reflected objects.
* Third pass
* Darken reflected objects
*/
uint8_t val = uint8_t(settings_reflectionValue * UINT8_MAX); uint8_t val = uint8_t(settings_reflectionValue * UINT8_MAX);
uint32_t factor = (val << 24) uint32_t factor = (val << 24)
@ -1213,19 +1212,16 @@ int _main_(int /*_argc*/, char** /*_argv*/)
; ;
s_renderStates[RenderState::StencilReflection_DarkenReflections].m_blendFactorRgba = factor; s_renderStates[RenderState::StencilReflection_DarkenReflections].m_blendFactorRgba = factor;
//floor // Floor.
hplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_2 hplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_2
, floorMtx , floorMtx
, programColorBlack , programColorBlack
, s_renderStates[RenderState::StencilReflection_DarkenReflections] , s_renderStates[RenderState::StencilReflection_DarkenReflections]
); );
/** // Fourth pass - Draw plane. (blend plane with what's behind it)
* Fourth pass
* Draw plane. (blend plane with what's behind it)
*/
//floor // Floor.
hplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_3 hplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_3
, floorMtx , floorMtx
, programTextureLightning , programTextureLightning
@ -1233,19 +1229,16 @@ int _main_(int /*_argc*/, char** /*_argv*/)
, fieldstoneTex , fieldstoneTex
); );
/** // Fifth pass - Draw everything else but the plane.
* Fifth pass
* Draw everything else but the plane.
*/
//bunny // Bunny.
bunnyMesh.submit(RENDER_VIEWID_RANGE1_PASS_4 bunnyMesh.submit(RENDER_VIEWID_RANGE1_PASS_4
, bunnyMtx , bunnyMtx
, programColorLightning , programColorLightning
, s_renderStates[RenderState::StencilReflection_DrawScene] , s_renderStates[RenderState::StencilReflection_DrawScene]
); );
//columns // Columns.
for (uint8_t ii = 0; ii < 4; ++ii) for (uint8_t ii = 0; ii < 4; ++ii)
{ {
columnMesh.submit(RENDER_VIEWID_RANGE1_PASS_4 columnMesh.submit(RENDER_VIEWID_RANGE1_PASS_4
@ -1256,24 +1249,22 @@ int _main_(int /*_argc*/, char** /*_argv*/)
} }
} }
break; break;
case ProjectionShadowsScene: case ProjectionShadowsScene:
{ {
/** // First pass - Draw entire scene. (ambient only).
* First pass
* Draw entire scene. (ambient only)
*/
params.m_ambientPass = 1.0f; params.m_ambientPass = 1.0f;
params.m_lightningPass = 1.0f; params.m_lightningPass = 1.0f;
bgfx::setUniform(u_params, (const void*)&params); bgfx::setUniform(u_params, (const void*)&params);
//bunny // Bunny.
bunnyMesh.submit(RENDER_VIEWID_RANGE1_PASS_0 bunnyMesh.submit(RENDER_VIEWID_RANGE1_PASS_0
, bunnyMtx , bunnyMtx
, programColorLightning , programColorLightning
, s_renderStates[RenderState::ProjectionShadows_DrawAmbient] , s_renderStates[RenderState::ProjectionShadows_DrawAmbient]
); );
//floor // Floor.
hplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_0 hplaneMesh.submit(RENDER_VIEWID_RANGE1_PASS_0
, floorMtx , floorMtx
, programTextureLightning , programTextureLightning
@ -1281,7 +1272,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
, fieldstoneTex , fieldstoneTex
); );
//cubes // Cubes.
for (uint8_t ii = 0; ii < numCubes; ++ii) for (uint8_t ii = 0; ii < numCubes; ++ii)
{ {
cubeMesh.submit(RENDER_VIEWID_RANGE1_PASS_0 cubeMesh.submit(RENDER_VIEWID_RANGE1_PASS_0
@ -1292,36 +1283,31 @@ int _main_(int /*_argc*/, char** /*_argv*/)
); );
} }
//ground plane // Ground plane.
float ground[4]; float ground[4];
float plane_pos[3] = { 0.0f, 0.0f, 0.0f }; float plane_pos[3] = { 0.0f, 0.0f, 0.0f };
float normal[3] = { 0.0f, 1.0f, 0.0f }; float normal[3] = { 0.0f, 1.0f, 0.0f };
memcpy(ground, normal, sizeof(float) * 3); memcpy(ground, normal, sizeof(float) * 3);
ground[3] = -vec3Dot(plane_pos, normal) - 0.01f; // - 0.01 against z-fighting ground[3] = -vec3Dot(plane_pos, normal) - 0.01f; // - 0.01 against z-fighting
/**
* For each light:
*/
for (uint8_t ii = 0; ii < numLights; ++ii) for (uint8_t ii = 0; ii < numLights; ++ii)
{ {
uint8_t viewId = RENDER_VIEWID_RANGE5_PASS_6+ii; uint8_t viewId = RENDER_VIEWID_RANGE5_PASS_6+ii;
clearView(viewId, BGFX_CLEAR_STENCIL_BIT, clearValues); clearView(viewId, BGFX_CLEAR_STENCIL_BIT, clearValues);
/** // Draw shadow projection of scene objects.
* Draw shadow projection of scene objects.
*/
//get homogeneous light pos // Get homogeneous light pos.
float* lightPos = lightPosRadius[ii]; float* lightPos = lightPosRadius[ii];
float pos[4]; float pos[4];
memcpy(pos, lightPos, sizeof(float) * 3); memcpy(pos, lightPos, sizeof(float) * 3);
pos[3] = 1.0f; pos[3] = 1.0f;
//calculate shadow mtx for current light // Calculate shadow mtx for current light.
float shadowMtx[16]; float shadowMtx[16];
mtxShadow(shadowMtx, ground, pos); mtxShadow(shadowMtx, ground, pos);
//submit bunny's shadow // Submit bunny's shadow.
float mtxShadowedBunny[16]; float mtxShadowedBunny[16];
mtxMul(mtxShadowedBunny, bunnyMtx, shadowMtx); mtxMul(mtxShadowedBunny, bunnyMtx, shadowMtx);
bunnyMesh.submit(viewId bunnyMesh.submit(viewId
@ -1330,7 +1316,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
, s_renderStates[RenderState::ProjectionShadows_CraftStencil] , s_renderStates[RenderState::ProjectionShadows_CraftStencil]
); );
//submit cube shadows // Submit cube shadows.
float mtxShadowedCube[16]; float mtxShadowedCube[16];
for (uint8_t ii = 0; ii < numCubes; ++ii) for (uint8_t ii = 0; ii < numCubes; ++ii)
{ {
@ -1342,14 +1328,13 @@ int _main_(int /*_argc*/, char** /*_argv*/)
); );
} }
/** // Draw entire scene. (lightning pass only. blending is on)
* Draw entire scene. (lightning pass only. blending is on)
*/
params.m_ambientPass = 0.0f; params.m_ambientPass = 0.0f;
params.m_lightningPass = 1.0f; params.m_lightningPass = 1.0f;
bgfx::setUniform(u_params, (const void*)&params); bgfx::setUniform(u_params, (const void*)&params);
//set blending factor based on number of lights // Set blending factor based on number of lights.
uint32_t factor = 0xff / (numLights < 1 ? 1 : numLights); uint32_t factor = 0xff / (numLights < 1 ? 1 : numLights);
factor = (factor << 24) factor = (factor << 24)
| (factor << 16) | (factor << 16)
@ -1358,14 +1343,14 @@ int _main_(int /*_argc*/, char** /*_argv*/)
; ;
s_renderStates[RenderState::ProjectionShadows_DrawDiffuse].m_blendFactorRgba = factor; s_renderStates[RenderState::ProjectionShadows_DrawDiffuse].m_blendFactorRgba = factor;
//bunny // Bunny.
bunnyMesh.submit(viewId bunnyMesh.submit(viewId
, bunnyMtx , bunnyMtx
, programColorLightning , programColorLightning
, s_renderStates[RenderState::ProjectionShadows_DrawDiffuse] , s_renderStates[RenderState::ProjectionShadows_DrawDiffuse]
); );
//floor // Floor.
hplaneMesh.submit(viewId hplaneMesh.submit(viewId
, floorMtx , floorMtx
, programTextureLightning , programTextureLightning
@ -1373,7 +1358,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
, fieldstoneTex , fieldstoneTex
); );
//cubes // Cubes.
for (uint8_t ii = 0; ii < numCubes; ++ii) for (uint8_t ii = 0; ii < numCubes; ++ii)
{ {
cubeMesh.submit(viewId cubeMesh.submit(viewId
@ -1385,7 +1370,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
} }
} }
//reset these to default // Reset these to default..
params.m_ambientPass = 1.0f; params.m_ambientPass = 1.0f;
params.m_lightningPass = 1.0f; params.m_lightningPass = 1.0f;
bgfx::setUniform(u_params, (const void*)&params); bgfx::setUniform(u_params, (const void*)&params);
@ -1412,7 +1397,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
); );
} }
//draw floor bottom // Draw floor bottom.
float floorBottomMtx[16]; float floorBottomMtx[16];
mtxScaleRotateTranslate(floorBottomMtx mtxScaleRotateTranslate(floorBottomMtx
, 20.0f //scaleX , 20.0f //scaleX
@ -1433,7 +1418,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
, figureTex , figureTex
); );
//setup view rect and transform for all used views // Setup view rect and transform for all used views.
setViewRectTransformMask(s_viewMask, viewState); setViewRectTransformMask(s_viewMask, viewState);
s_viewMask = 0; s_viewMask = 0;
@ -1446,7 +1431,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
s_clearMask = 0; s_clearMask = 0;
} }
// Cleanup // Cleanup.
bunnyMesh.unload(); bunnyMesh.unload();
columnMesh.unload(); columnMesh.unload();
cubeMesh.unload(); cubeMesh.unload();