diff --git a/examples/28-wireframe/fs_wf_mesh.sc b/examples/28-wireframe/fs_wf_mesh.sc new file mode 100644 index 000000000..03888c7c6 --- /dev/null +++ b/examples/28-wireframe/fs_wf_mesh.sc @@ -0,0 +1,78 @@ +$input v_view, v_bc, v_normal + +/* + * Copyright 2016 Dario Manesku. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include "../common/common.sh" +#include "uniforms.sh" + +const vec3 shEnv[9] = vec3[9](vec3( 0.967757057878229854, 0.976516067990363390, 0.891218272348969998) /* Band 0 */ + , vec3(-0.384163503608655643, -0.423492289131209787, -0.425532726148547868) /* Band 1 */ + , vec3( 0.055906294587354334, 0.056627436881069373, 0.069969936396987467) + , vec3( 0.120985157386215209, 0.119297994074027414, 0.117111965829213599) + , vec3(-0.176711633774331106, -0.170331404095516392, -0.151345020570876621) /* Band 2 */ + , vec3(-0.124682114349692147, -0.119340785411183953, -0.096300354204368860) + , vec3( 0.001852378550138503, -0.032592784164597745, -0.088204495001329680) + , vec3( 0.296365482782109446, 0.281268696656263029, 0.243328223888495510) + , vec3(-0.079826665303240341, -0.109340956251195970, -0.157208859664677764) + ); + +vec3 evalSh(vec3 _dir) +{ +# define k01 0.2820947918 // sqrt( 1/PI)/2 +# define k02 0.4886025119 // sqrt( 3/PI)/2 +# define k03 1.0925484306 // sqrt(15/PI)/2 +# define k04 0.3153915652 // sqrt( 5/PI)/4 +# define k05 0.5462742153 // sqrt(15/PI)/4 + + vec3 nn = _dir.zxy; + + float sh[9]; + sh[0] = k01; + sh[1] = -k02*nn.y; + sh[2] = k02*nn.z; + sh[3] = -k02*nn.x; + sh[4] = k03*nn.y*nn.x; + sh[5] = -k03*nn.y*nn.z; + sh[6] = k04*(3.0*nn.z*nn.z-1.0); + sh[7] = -k03*nn.x*nn.z; + sh[8] = k05*(nn.x*nn.x-nn.y*nn.y); + + vec3 rgb = vec3_splat(0.0); + rgb += shEnv[0] * sh[0] * 1.0; + rgb += shEnv[1] * sh[1] * 2.0/2.5; + rgb += shEnv[2] * sh[2] * 2.0/2.5; + rgb += shEnv[3] * sh[3] * 2.0/2.5; + rgb += shEnv[4] * sh[4] * 1.0/2.5; + rgb += shEnv[5] * sh[5] * 0.5; + rgb += shEnv[6] * sh[6] * 0.5; + rgb += shEnv[7] * sh[7] * 0.5; + rgb += shEnv[8] * sh[8] * 0.5; + + return rgb; +} + +void main() +{ + vec3 nn = normalize(v_normal); + vec3 col = evalSh(nn); + + if (0.0 != u_drawEdges) + { + vec3 wfColor = u_wfColor; + float wfOpacity = u_wfOpacity; + float thickness = u_wfThickness; + + vec3 fw = abs(dFdx(v_bc)) + abs(dFdy(v_bc)); + vec3 val = smoothstep(vec3_splat(0.0), vec3_splat(fw*thickness), v_bc); + float edge = min(min(val.x, val.y), val.z); // Gets to 0.0 when close to edges. + + vec3 edgeCol = mix(col, wfColor, wfOpacity); + col = mix(edgeCol, col, edge); + } + + gl_FragColor.xyz = col; + gl_FragColor.w = 1.0; +} diff --git a/examples/28-wireframe/fs_wf_wireframe.sc b/examples/28-wireframe/fs_wf_wireframe.sc new file mode 100644 index 000000000..a16f03294 --- /dev/null +++ b/examples/28-wireframe/fs_wf_wireframe.sc @@ -0,0 +1,26 @@ +$input v_view, v_bc + +/* + * Copyright 2016 Dario Manesku. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include "../common/common.sh" +#include "uniforms.sh" + +void main() +{ + vec3 color = u_wfColor; + float opacity = u_wfOpacity; + float thickness = u_wfThickness; + + if (!gl_FrontFacing) { opacity *= 0.5; } + + vec3 fw = abs(dFdx(v_bc)) + abs(dFdy(v_bc)); + vec3 val = smoothstep(vec3_splat(0.0), vec3_splat(fw*thickness), v_bc); + float edge = min(min(val.x, val.y), val.z); // Gets to 0.0 around the edges. + + vec4 rgba = vec4(color, (1.0-edge)*opacity); + gl_FragColor = rgba; +} + diff --git a/examples/28-wireframe/makefile b/examples/28-wireframe/makefile new file mode 100644 index 000000000..4f81fb5bf --- /dev/null +++ b/examples/28-wireframe/makefile @@ -0,0 +1,17 @@ +# +# Copyright 2011-2016 Branimir Karadzic. All rights reserved. +# License: http://www.opensource.org/licenses/BSD-2-Clause +# + +BGFX_DIR=../.. +RUNTIME_DIR=$(BGFX_DIR)/examples/runtime +BUILD_DIR=../../.build + +include $(BGFX_DIR)/scripts/shader.mk + +rebuild: + @make -s --no-print-directory TARGET=0 clean all + @make -s --no-print-directory TARGET=1 clean all + @make -s --no-print-directory TARGET=2 clean all + @make -s --no-print-directory TARGET=3 clean all + @make -s --no-print-directory TARGET=4 clean all diff --git a/examples/28-wireframe/uniforms.sh b/examples/28-wireframe/uniforms.sh new file mode 100644 index 000000000..330555ee5 --- /dev/null +++ b/examples/28-wireframe/uniforms.sh @@ -0,0 +1,12 @@ +/* + * Copyright 2016 Dario Manesku. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +uniform vec4 u_params[3]; +#define u_camPos u_params[0].xyz +#define u_unused0 u_params[0].w +#define u_wfColor u_params[1].xyz +#define u_wfOpacity u_params[1].w +#define u_drawEdges u_params[2].x +#define u_wfThickness u_params[2].y diff --git a/examples/28-wireframe/varying.def.sc b/examples/28-wireframe/varying.def.sc new file mode 100644 index 000000000..c0c52962a --- /dev/null +++ b/examples/28-wireframe/varying.def.sc @@ -0,0 +1,7 @@ +vec3 v_view : TEXCOORD0 = vec3(0.0, 0.0, 0.0); +vec3 v_bc : TEXCOORD1 = vec3(0.0, 0.0, 0.0); +vec3 v_normal : NORMAL = vec3(0.0, 0.0, 1.0); + +vec3 a_position : POSITION; +vec3 a_color1 : COLOR1; +vec3 a_normal : NORMAL; diff --git a/examples/28-wireframe/vs_wf_mesh.sc b/examples/28-wireframe/vs_wf_mesh.sc new file mode 100644 index 000000000..3f51abc59 --- /dev/null +++ b/examples/28-wireframe/vs_wf_mesh.sc @@ -0,0 +1,21 @@ +$input a_position, a_color1, a_normal +$output v_view, v_bc, v_normal + +/* + * Copyright 2016 Dario Manesku. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include "../common/common.sh" +#include "uniforms.sh" + +void main() +{ + gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) ); + + v_view = u_camPos - mul(u_model[0], vec4(a_position, 1.0) ).xyz; + v_bc = a_color1; + + vec3 normal = a_normal.xyz*2.0 - 1.0; + v_normal = mul(u_model[0], vec4(normal, 0.0) ).xyz; +} diff --git a/examples/28-wireframe/vs_wf_wireframe.sc b/examples/28-wireframe/vs_wf_wireframe.sc new file mode 100644 index 000000000..1956b0d64 --- /dev/null +++ b/examples/28-wireframe/vs_wf_wireframe.sc @@ -0,0 +1,19 @@ +$input a_position, a_color1 +$output v_view, v_bc + +/* + * Copyright 2016 Dario Manesku. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include "../common/common.sh" +#include "uniforms.sh" + +void main() +{ + gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) ); + + v_view = u_camPos - mul(u_model[0], vec4(a_position, 1.0) ).xyz; + v_bc = a_color1; +} + diff --git a/examples/28-wireframe/wireframe.cpp b/examples/28-wireframe/wireframe.cpp new file mode 100644 index 000000000..836bbda42 --- /dev/null +++ b/examples/28-wireframe/wireframe.cpp @@ -0,0 +1,564 @@ +/* + * Copyright 2016 Dario Manesku. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include "common.h" +#include "bgfx_utils.h" +#include "imgui/imgui.h" + +class Wireframe : public entry::AppI +{ + struct DrawMode + { + enum + { + WireframeShaded, + Wireframe, + Shaded, + }; + }; + + struct Camera + { + Camera() + { + reset(); + } + + void reset() + { + m_target.curr[0] = 0.0f; + m_target.curr[1] = 0.0f; + m_target.curr[2] = 0.0f; + m_target.dest[0] = 0.0f; + m_target.dest[1] = 0.0f; + m_target.dest[2] = 0.0f; + + m_pos.curr[0] = 0.0f; + m_pos.curr[1] = 0.0f; + m_pos.curr[2] = -2.0f; + m_pos.dest[0] = 0.0f; + m_pos.dest[1] = 0.0f; + m_pos.dest[2] = -2.0f; + + m_orbit[0] = 0.0f; + m_orbit[1] = 0.0f; + } + + void mtxLookAt(float* _outViewMtx) + { + bx::mtxLookAt(_outViewMtx, m_pos.curr, m_target.curr); + } + + void orbit(float _dx, float _dy) + { + m_orbit[0] += _dx; + m_orbit[1] += _dy; + } + + void dolly(float _dz) + { + const float cnear = 0.01f; + const float cfar = 10.0f; + + const float toTarget[3] = + { + m_target.dest[0] - m_pos.dest[0], + m_target.dest[1] - m_pos.dest[1], + m_target.dest[2] - m_pos.dest[2], + }; + const float toTargetLen = bx::vec3Length(toTarget); + const float invToTargetLen = 1.0f/(toTargetLen+FLT_MIN); + const float toTargetNorm[3] = + { + toTarget[0]*invToTargetLen, + toTarget[1]*invToTargetLen, + toTarget[2]*invToTargetLen, + }; + + float delta = toTargetLen*_dz; + float newLen = toTargetLen + delta; + if ( (cnear < newLen || _dz < 0.0f) + && (newLen < cfar || _dz > 0.0f) ) + { + m_pos.dest[0] += toTargetNorm[0]*delta; + m_pos.dest[1] += toTargetNorm[1]*delta; + m_pos.dest[2] += toTargetNorm[2]*delta; + } + } + + void consumeOrbit(float _amount) + { + float consume[2]; + consume[0] = m_orbit[0]*_amount; + consume[1] = m_orbit[1]*_amount; + m_orbit[0] -= consume[0]; + m_orbit[1] -= consume[1]; + + const float toPos[3] = + { + m_pos.curr[0] - m_target.curr[0], + m_pos.curr[1] - m_target.curr[1], + m_pos.curr[2] - m_target.curr[2], + }; + const float toPosLen = bx::vec3Length(toPos); + const float invToPosLen = 1.0f/(toPosLen+FLT_MIN); + const float toPosNorm[3] = + { + toPos[0]*invToPosLen, + toPos[1]*invToPosLen, + toPos[2]*invToPosLen, + }; + + float ll[2]; + latLongFromVec(ll[0], ll[1], toPosNorm); + ll[0] += consume[0]; + ll[1] -= consume[1]; + ll[1] = bx::fclamp(ll[1], 0.02f, 0.98f); + + float tmp[3]; + vecFromLatLong(tmp, ll[0], ll[1]); + + float diff[3]; + diff[0] = (tmp[0]-toPosNorm[0])*toPosLen; + diff[1] = (tmp[1]-toPosNorm[1])*toPosLen; + diff[2] = (tmp[2]-toPosNorm[2])*toPosLen; + + m_pos.curr[0] += diff[0]; + m_pos.curr[1] += diff[1]; + m_pos.curr[2] += diff[2]; + m_pos.dest[0] += diff[0]; + m_pos.dest[1] += diff[1]; + m_pos.dest[2] += diff[2]; + } + + void update(float _dt) + { + const float amount = bx::fmin(_dt/0.12f, 1.0f); + + consumeOrbit(amount); + + m_target.curr[0] = bx::flerp(m_target.curr[0], m_target.dest[0], amount); + m_target.curr[1] = bx::flerp(m_target.curr[1], m_target.dest[1], amount); + m_target.curr[2] = bx::flerp(m_target.curr[2], m_target.dest[2], amount); + m_pos.curr[0] = bx::flerp(m_pos.curr[0], m_pos.dest[0], amount); + m_pos.curr[1] = bx::flerp(m_pos.curr[1], m_pos.dest[1], amount); + m_pos.curr[2] = bx::flerp(m_pos.curr[2], m_pos.dest[2], amount); + } + + static inline void vecFromLatLong(float _vec[3], float _u, float _v) + { + const float phi = _u * 2.0f*bx::pi; + const float theta = _v * bx::pi; + + const float st = bx::fsin(theta); + const float sp = bx::fsin(phi); + const float ct = bx::fcos(theta); + const float cp = bx::fcos(phi); + + _vec[0] = -st*sp; + _vec[1] = ct; + _vec[2] = -st*cp; + } + + static inline void latLongFromVec(float& _u, float& _v, const float _vec[3]) + { + const float phi = atan2f(_vec[0], _vec[2]); + const float theta = acosf(_vec[1]); + + _u = (bx::pi + phi)*bx::invPi*0.5f; + _v = theta*bx::invPi; + } + + struct Interp3f + { + float curr[3]; + float dest[3]; + }; + + Interp3f m_target; + Interp3f m_pos; + float m_orbit[2]; + }; + + struct Mouse + { + Mouse() + { + m_dx = 0.0f; + m_dy = 0.0f; + m_prevMx = 0.0f; + m_prevMx = 0.0f; + m_scroll = 0; + m_scrollPrev = 0; + } + + void update(float _mx, float _my, int32_t _mz, uint32_t _width, uint32_t _height) + { + const float widthf = float(int32_t(_width)); + const float heightf = float(int32_t(_height)); + + // Delta movement. + m_dx = float(_mx - m_prevMx)/widthf; + m_dy = float(_my - m_prevMy)/heightf; + + m_prevMx = _mx; + m_prevMy = _my; + + // Scroll. + m_scroll = _mz - m_scrollPrev; + m_scrollPrev = _mz; + } + + float m_dx; // Screen space. + float m_dy; + float m_prevMx; + float m_prevMy; + int32_t m_scroll; + int32_t m_scrollPrev; + }; + + struct MeshMtx + { + MeshMtx() + { + m_mesh = NULL; + } + + void init(const char* _path + , float _scale = 1.0f + , float _rotX = 0.0f + , float _rotY = 0.0f + , float _rotZ = 0.0f + , float _transX = 0.0f + , float _transY = 0.0f + , float _transZ = 0.0f + ) + { + m_mesh = meshLoad(_path); + bx::mtxSRT(m_mtx + , _scale + , _scale + , _scale + , _rotX + , _rotY + , _rotZ + , _transX + , _transY + , _transZ + ); + } + + void destroy() + { + if (NULL != m_mesh) + { + meshUnload(m_mesh); + } + } + + Mesh* m_mesh; + float m_mtx[16]; + }; + + struct Uniforms + { + enum { NumVec4 = 3 }; + + void init() + { + m_camPos[0] = 0.0f; + m_camPos[1] = 1.0f; + m_camPos[2] = -2.5f; + m_wfColor[0] = 1.0f; + m_wfColor[1] = 0.0f; + m_wfColor[2] = 0.0f; + m_wfOpacity = 0.7f; + m_drawEdges = 0.0f; + m_wfThickness = 1.5f; + + u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4, NumVec4); + } + + void submit() + { + bgfx::setUniform(u_params, m_params, NumVec4); + } + + void destroy() + { + bgfx::destroyUniform(u_params); + } + + union + { + struct + { + /*0*/struct { float m_camPos[3], m_unused0; }; + /*1*/struct { float m_wfColor[3], m_wfOpacity; }; + /*2*/struct { float m_drawEdges, m_wfThickness, m_unused2[2]; }; + }; + + float m_params[NumVec4*4]; + }; + + bgfx::UniformHandle u_params; + }; + + void init(int _argc, char** _argv) BX_OVERRIDE + { + Args args(_argc, _argv); + + m_width = 1280; + m_height = 720; + m_debug = BGFX_DEBUG_TEXT; + m_reset = BGFX_RESET_VSYNC; + + bgfx::init(args.m_type, args.m_pciId); + bgfx::reset(m_width, m_height, m_reset); + + // Enable m_debug text. + bgfx::setDebug(m_debug); + + // Set view 0 clear state. + bgfx::setViewClear(0 + , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH + , 0x303030ff + , 1.0f + , 0 + ); + + m_wfProgram = loadProgram("vs_wf_wireframe", "fs_wf_wireframe"); + m_meshProgram = loadProgram("vs_wf_mesh", "fs_wf_mesh"); + + m_uniforms.init(); + + m_meshes[0].init("meshes/bunny.bin", 1.0f, 0.0f, bx::pi, 0.0f, 0.0f, -0.8f, 0.0f); + m_meshes[1].init("meshes/hollowcube.bin", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + m_meshes[2].init("meshes/orb.bin", 1.2f, 0.0f, 0.0f, 0.0f, 0.0f, -0.65f, 0.0f); + + // Imgui. + imguiCreate(); + + m_oldWidth = 0; + m_oldHeight = 0; + m_oldReset = m_reset; + + m_meshSelection = 1; + m_drawMode = DrawMode::WireframeShaded; + m_scrollArea = 0; + m_showWfColor = true; + } + + virtual int shutdown() BX_OVERRIDE + { + // Cleanup. + imguiDestroy(); + + m_meshes[0].destroy(); + m_meshes[1].destroy(); + m_meshes[2].destroy(); + + bgfx::destroyProgram(m_wfProgram); + bgfx::destroyProgram(m_meshProgram); + + m_uniforms.destroy(); + + // Shutdown bgfx. + bgfx::shutdown(); + + return 0; + } + + bool update() BX_OVERRIDE + { + if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) ) + { + if (m_oldWidth != m_width + || m_oldHeight != m_height + || m_oldReset != m_reset) + { + // Recreate variable size render targets when resolution changes. + m_oldWidth = m_width; + m_oldHeight = m_height; + m_oldReset = m_reset; + } + + 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 + , m_width + , m_height + ); + + imguiBeginScrollArea("Settings" + , m_width - m_width / 5 - 10 + , 10 + , m_width / 5 + , 492 + , &m_scrollArea + ); + + imguiSeparatorLine(1); imguiIndent(8); imguiLabel("Draw mode:"); imguiUnindent(8); imguiSeparatorLine(1); + imguiSeparator(4); + { + imguiIndent(); + m_drawMode = imguiChoose(m_drawMode + , "Wireframe + Shaded" + , "Wireframe" + , "Shaded" + ); + imguiUnindent(); + } + imguiSeparator(8); + + const bool wfEnabled = (DrawMode::Shaded != m_drawMode); + imguiSeparatorLine(1); imguiIndent(8); imguiLabel("Wireframe:", wfEnabled); imguiUnindent(8); imguiSeparatorLine(1); + imguiSeparator(4); + { + imguiColorWheel("Color", m_uniforms.m_wfColor, m_showWfColor, 0.6f, wfEnabled); + imguiIndent(); + imguiSlider("Opacity", m_uniforms.m_wfOpacity, 0.1f, 1.0f, 0.1f, wfEnabled); + imguiSlider("Thickness", m_uniforms.m_wfThickness, 0.6f, 2.2f, 0.1f, wfEnabled); + imguiUnindent(); + } + imguiSeparator(8); + + imguiSeparatorLine(1); imguiIndent(8); imguiLabel("Mesh:"); imguiUnindent(8); imguiSeparatorLine(1); + imguiSeparator(4); + { + imguiIndent(); + const uint32_t prevMeshSel = m_meshSelection; + m_meshSelection = imguiChoose(m_meshSelection + , "Bunny" + , "Orb" + , "Hollowcubes" + ); + if (prevMeshSel != m_meshSelection) + { + m_camera.reset(); + } + imguiUnindent(); + } + imguiSeparator(8); + + imguiEndScrollArea(); + imguiEndFrame(); + + // 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::touch(0); + + 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 double deltaTimeSec = double(frameTime)/freq; + + // Use m_debug font to print information about this example. + bgfx::dbgTextClear(); + bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/28-wirefame"); + bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Drawing wireframe mesh."); + bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs); + + // Setup view. + bgfx::setViewRect(0, 0, 0, bgfx::BackbufferRatio::Equal); + bgfx::setViewClear(0, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH, 0x303030ff, 1.0f, 0); + + const bool mouseOverGui = imguiMouseOverArea(); + m_mouse.update(m_mouseState.m_mx, m_mouseState.m_my, m_mouseState.m_mz, m_width, m_height); + if (!mouseOverGui) + { + if (m_mouseState.m_buttons[entry::MouseButton::Left]) + { + m_camera.orbit(m_mouse.m_dx, m_mouse.m_dy); + } + else if (m_mouseState.m_buttons[entry::MouseButton::Right]) + { + m_camera.dolly(m_mouse.m_dx + m_mouse.m_dy); + } + else if (0 != m_mouse.m_scroll) + { + m_camera.dolly(float(m_mouse.m_scroll)*0.1f); + } + } + + float view[16]; + float proj[16]; + m_camera.update(deltaTimeSec); + memcpy(m_uniforms.m_camPos, m_camera.m_pos.curr, 3*sizeof(float)); + m_camera.mtxLookAt(view); + bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f); + bgfx::setViewTransform(0, view, proj); + + m_uniforms.m_drawEdges = (DrawMode::WireframeShaded == m_drawMode) ? 1.0f : 0.0; + m_uniforms.submit(); + + if (DrawMode::Wireframe == m_drawMode) + { + uint64_t state = 0 + | BGFX_STATE_RGB_WRITE + | BGFX_STATE_ALPHA_WRITE + | BGFX_STATE_DEPTH_WRITE + | BGFX_STATE_CULL_CCW + | BGFX_STATE_MSAA + | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) + ; + meshSubmit(m_meshes[m_meshSelection].m_mesh, 0, m_wfProgram, m_meshes[m_meshSelection].m_mtx, state); + } + else + { + uint64_t state = 0 + | BGFX_STATE_RGB_WRITE + | BGFX_STATE_ALPHA_WRITE + | BGFX_STATE_DEPTH_TEST_LESS + | BGFX_STATE_DEPTH_WRITE + | BGFX_STATE_CULL_CCW + | BGFX_STATE_MSAA + ; + meshSubmit(m_meshes[m_meshSelection].m_mesh, 0, m_meshProgram, m_meshes[m_meshSelection].m_mtx, state); + } + + // Advance to next frame. Rendering thread will be kicked to + // process submitted rendering primitives. + bgfx::frame(); + + return true; + } + + return false; + } + + entry::MouseState m_mouseState; + + bgfx::ProgramHandle m_wfProgram; + bgfx::ProgramHandle m_meshProgram; + + uint32_t m_width; + uint32_t m_height; + uint32_t m_debug; + uint32_t m_reset; + uint32_t m_lumBgra8; + + uint32_t m_oldWidth; + uint32_t m_oldHeight; + uint32_t m_oldReset; + + Camera m_camera; + Mouse m_mouse; + Uniforms m_uniforms; + MeshMtx m_meshes[3]; + uint32_t m_meshSelection; + uint32_t m_drawMode; // Holds data for 'DrawMode'. + + bool m_showWfColor; + int32_t m_scrollArea; +}; + +ENTRY_IMPLEMENT_MAIN(Wireframe); diff --git a/examples/runtime/meshes/bunny.bin b/examples/runtime/meshes/bunny.bin index b34244a74..794ec22c7 100644 Binary files a/examples/runtime/meshes/bunny.bin and b/examples/runtime/meshes/bunny.bin differ diff --git a/examples/runtime/meshes/hollowcube.bin b/examples/runtime/meshes/hollowcube.bin index 69a4a38c1..0ea300901 100644 Binary files a/examples/runtime/meshes/hollowcube.bin and b/examples/runtime/meshes/hollowcube.bin differ diff --git a/examples/runtime/meshes/orb.bin b/examples/runtime/meshes/orb.bin index 336f36805..ac9455a25 100644 Binary files a/examples/runtime/meshes/orb.bin and b/examples/runtime/meshes/orb.bin differ diff --git a/examples/runtime/shaders/glsl/fs_wf_mesh.bin b/examples/runtime/shaders/glsl/fs_wf_mesh.bin new file mode 100644 index 000000000..47483c7e5 Binary files /dev/null and b/examples/runtime/shaders/glsl/fs_wf_mesh.bin differ diff --git a/examples/runtime/shaders/glsl/fs_wf_wireframe.bin b/examples/runtime/shaders/glsl/fs_wf_wireframe.bin new file mode 100644 index 000000000..46fb0d9a1 Binary files /dev/null and b/examples/runtime/shaders/glsl/fs_wf_wireframe.bin differ diff --git a/examples/runtime/shaders/glsl/vs_wf_mesh.bin b/examples/runtime/shaders/glsl/vs_wf_mesh.bin new file mode 100644 index 000000000..558881a8f Binary files /dev/null and b/examples/runtime/shaders/glsl/vs_wf_mesh.bin differ diff --git a/examples/runtime/shaders/glsl/vs_wf_wireframe.bin b/examples/runtime/shaders/glsl/vs_wf_wireframe.bin new file mode 100644 index 000000000..70a464fa9 Binary files /dev/null and b/examples/runtime/shaders/glsl/vs_wf_wireframe.bin differ diff --git a/scripts/genie.lua b/scripts/genie.lua index 22a7dd361..a0fa5b712 100644 --- a/scripts/genie.lua +++ b/scripts/genie.lua @@ -420,6 +420,7 @@ exampleProject("23-vectordisplay") exampleProject("24-nbody") exampleProject("26-occlusion") exampleProject("27-terrain") +exampleProject("28-wireframe") -- C99 source doesn't compile under WinRT settings if not premake.vstudio.iswinrt() then diff --git a/tools/geometryc/geometryc.cpp b/tools/geometryc/geometryc.cpp index 129c1653d..fe4de46ad 100644 --- a/tools/geometryc/geometryc.cpp +++ b/tools/geometryc/geometryc.cpp @@ -81,6 +81,7 @@ struct Index3 int32_t m_texcoord; int32_t m_normal; int32_t m_vertexIndex; + int32_t m_vbc; // Barycentric ID. Holds eigher 0, 1 or 2. }; typedef stl::unordered_map Index3Map; @@ -387,6 +388,7 @@ void help(const char* _error = NULL) " 0 - unpacked 8 bytes (default).\n" " 1 - packed 4 bytes.\n" " --tangent Calculate tangent vectors (packing mode is the same as normal).\n" + " --barycentric Adds barycentric vertex attribute (packed in bgfx::Attrib::Color1).\n" " -c, --compress Compress indices.\n" "\n" @@ -450,6 +452,7 @@ int main(int _argc, const char* _argv[]) bool ccw = cmdLine.hasArg("ccw"); bool flipV = cmdLine.hasArg("flipv"); bool hasTangent = cmdLine.hasArg("tangent"); + bool hasBc = cmdLine.hasArg("barycentric"); FILE* file = fopen(filePath, "r"); if (NULL == file) @@ -513,6 +516,14 @@ int main(int _argc, const char* _argv[]) index.m_texcoord = -1; index.m_normal = -1; index.m_vertexIndex = -1; + if (hasBc) + { + index.m_vbc = edge < 3 ? edge : (1+(edge+1) )&1; + } + else + { + index.m_vbc = 0; + } char* vertex = argv[edge+1]; char* texcoord = strchr(vertex, '/'); @@ -542,7 +553,8 @@ int main(int _argc, const char* _argv[]) uint64_t hash0 = index.m_position; uint64_t hash1 = uint64_t(index.m_texcoord)<<20; uint64_t hash2 = uint64_t(index.m_normal)<<40; - uint64_t hash = hash0^hash1^hash2; + uint64_t hash3 = uint64_t(index.m_vbc)<<60; + uint64_t hash = hash0^hash1^hash2^hash3; stl::pair result = indexMap.insert(stl::make_pair(hash, index) ); if (!result.second) @@ -755,6 +767,11 @@ int main(int _argc, const char* _argv[]) decl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true); } + if (hasBc) + { + decl.add(bgfx::Attrib::Color1, 4, bgfx::AttribType::Uint8, true); + } + if (hasTexcoord) { switch (packUv) @@ -914,6 +931,17 @@ int main(int _argc, const char* _argv[]) *color0 = rgbaToAbgr(numVertices%255, numIndices%255, 0, 0xff); } + if (hasBc) + { + const float bc[3] = + { + (index.m_vbc == 0) ? 1.0f : 0.0f, + (index.m_vbc == 1) ? 1.0f : 0.0f, + (index.m_vbc == 2) ? 1.0f : 0.0f, + }; + bgfx::vertexPack(bc, true, bgfx::Attrib::Color1, decl, vertices); + } + if (hasTexcoord) { float uv[2];