| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930 |
- /*
- * Copyright 2019 Daniel Gavin. All rights reserved.
- * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
- */
- /*
- * Reference(s):
- *
- * - Adaptive GPU Tessellation with Compute Shaders by Jad Khoury, Jonathan Dupuy, and Christophe Riccio
- * http://onrendering.com/data/papers/isubd/isubd.pdf
- * https://github.com/jdupuy/opengl-framework/tree/master/demo-isubd-terrain#implicit-subdivision-on-the-gpu
- */
- #include <bx/allocator.h>
- #include <bx/debug.h>
- #include <bx/file.h>
- #include <bx/math.h>
- #include "bgfx_utils.h"
- #include "bounds.h"
- #include "camera.h"
- #include "common.h"
- #include "imgui/imgui.h"
- namespace
- {
- static const char* s_shaderOptions[] =
- {
- "Normal",
- "Diffuse"
- };
- static const float s_verticesL0[] =
- {
- 0.0f, 0.0f,
- 1.0f, 0.0f,
- 0.0f, 1.0f,
- };
- static const uint32_t s_indexesL0[] = { 0u, 1u, 2u };
- static const float s_verticesL1[] =
- {
- 0.0f, 1.0f,
- 0.5f, 0.5f,
- 0.0f, 0.5f,
- 0.0f, 0.0f,
- 0.5f, 0.0f,
- 1.0f, 0.0f,
- };
- static const uint32_t s_indexesL1[] =
- {
- 1u, 0u, 2u,
- 1u, 2u, 3u,
- 1u, 3u, 4u,
- 1u, 4u, 5u,
- };
- static const float s_verticesL2[] =
- {
- 0.25f, 0.75f,
- 0.0f, 1.0f,
- 0.0f, 0.75f,
- 0.0f, 0.5f,
- 0.25f, 0.5f,
- 0.5f, 0.5f,
- 0.25f, 0.25f,
- 0.0f, 0.25f,
- 0.0f, 0.0f,
- 0.25f, 0.0f,
- 0.5f, 0.0f,
- 0.5f, 0.25f,
- 0.75f, 0.25f,
- 0.75f, 0.0f,
- 1.0f, 0.0f,
- };
- static const uint32_t s_indexesL2[] =
- {
- 0u, 1u, 2u,
- 0u, 2u, 3u,
- 0u, 3u, 4u,
- 0u, 4u, 5u,
- 6u, 5u, 4u,
- 6u, 4u, 3u,
- 6u, 3u, 7u,
- 6u, 7u, 8u,
- 6u, 8u, 9u,
- 6u, 9u, 10u,
- 6u, 10u, 11u,
- 6u, 11u, 5u,
- 12u, 5u, 11u,
- 12u, 11u, 10u,
- 12u, 10u, 13u,
- 12u, 13u, 14u,
- };
- static const float s_verticesL3[] =
- {
- 0.25f*0.5f, 0.75f*0.5f + 0.5f,
- 0.0f*0.5f, 1.0f*0.5f + 0.5f,
- 0.0f*0.5f, 0.75f*0.5f + 0.5f,
- 0.0f*0.5f , 0.5f*0.5f + 0.5f,
- 0.25f*0.5f, 0.5f*0.5f + 0.5f,
- 0.5f*0.5f, 0.5f*0.5f + 0.5f,
- 0.25f*0.5f, 0.25f*0.5f + 0.5f,
- 0.0f*0.5f, 0.25f*0.5f + 0.5f,
- 0.0f*0.5f, 0.0f*0.5f + 0.5f,
- 0.25f*0.5f, 0.0f*0.5f + 0.5f,
- 0.5f*0.5f, 0.0f*0.5f + 0.5f,
- 0.5f*0.5f, 0.25f*0.5f + 0.5f,
- 0.75f*0.5f, 0.25f*0.5f + 0.5f,
- 0.75f*0.5f, 0.0f*0.5f + 0.5f,
- 1.0f*0.5f, 0.0f*0.5f + 0.5f, //14
- 0.375f, 0.375f,
- 0.25f, 0.375f,
- 0.25f, 0.25f,
- 0.375f, 0.25f,
- 0.5f, 0.25f,
- 0.5f, 0.375f, //20
- 0.125f, 0.375f,
- 0.0f, 0.375f,
- 0.0f, 0.25f,
- 0.125f, 0.25f, //24
- 0.125f, 0.125f,
- 0.0f, 0.125f,
- 0.0f, 0.0f,
- 0.125f, 0.0f,
- 0.25f, 0.0f,
- 0.25f, 0.125f, //30
- 0.375f, 0.125f,
- 0.375f, 0.0f,
- 0.5f, 0.0f,
- 0.5f, 0.125f, //34
- 0.625f, 0.375f,
- 0.625f, 0.25f,
- 0.75f, 0.25f, //37
- 0.625f, 0.125f,
- 0.625f, 0.0f,
- 0.75f, 0.0f,
- 0.75f, 0.125f, //41
- 0.875f, 0.125f,
- 0.875f, 0.0f,
- 1.0f, 0.0f, //44
- };
- static const uint32_t s_indexesL3[] =
- {
- 0u, 1u, 2u,
- 0u, 2u, 3u,
- 0u, 3u, 4u,
- 0u, 4u, 5u,
- 6u, 5u, 4u,
- 6u, 4u, 3u,
- 6u, 3u, 7u,
- 6u, 7u, 8u,
- 6u, 8u, 9u,
- 6u, 9u, 10u,
- 6u, 10u, 11u,
- 6u, 11u, 5u,
- 12u, 5u, 11u,
- 12u, 11u, 10u,
- 12u, 10u, 13u,
- 12u, 13u, 14u, //End fo first big triangle
- 15u, 14u, 13u,
- 15u, 13u, 10u,
- 15u, 10u, 16u,
- 15u, 16u, 17u,
- 15u, 17u, 18u,
- 15u, 18u, 19u,
- 15u, 19u, 20u,
- 15u, 20u, 14u,
- 21u, 10u, 9u,
- 21u, 9u, 8u,
- 21u, 8u, 22u,
- 21u, 22u, 23u,
- 21u, 23u, 24u,
- 21u, 24u, 17u,
- 21u, 17u, 16u,
- 21u, 16u, 10u,
- 25u, 17u, 24u,
- 25u, 24u, 23u,
- 25u, 23u, 26u,
- 25u, 26u, 27u,
- 25u, 27u, 28u,
- 25u, 28u, 29u,
- 25u, 29u, 30u,
- 25u, 30u, 17u,
- 31u, 19u, 18u,
- 31u, 18u, 17u,
- 31u, 17u, 30u,
- 31u, 30u, 29u,
- 31u, 29u, 32u,
- 31u, 32u, 33u,
- 31u, 33u, 34u,
- 31u, 34u, 19u,
- 35u, 14u, 20u,
- 35u, 20u, 19u,
- 35u, 19u, 36u,
- 35u, 36u, 37u,
- 38u, 37u, 36u,
- 38u, 36u, 19u,
- 38u, 19u, 34u,
- 38u, 34u, 33u,
- 38u, 33u, 39u,
- 38u, 39u, 40u,
- 38u, 40u, 41u,
- 38u, 41u, 37u,
- 42u, 37u, 41u,
- 42u, 41u, 40u,
- 42u, 40u, 43u,
- 42u, 43u, 44u,
- };
- enum
- {
- PROGRAM_TERRAIN_NORMAL,
- PROGRAM_TERRAIN,
- SHADING_COUNT
- };
- enum
- {
- BUFFER_SUBD
- };
- enum
- {
- PROGRAM_SUBD_CS_LOD,
- PROGRAM_UPDATE_INDIRECT,
- PROGRAM_INIT_INDIRECT,
- PROGRAM_UPDATE_DRAW,
- PROGRAM_COUNT
- };
- enum
- {
- TERRAIN_DMAP_SAMPLER,
- TERRAIN_SMAP_SAMPLER,
- SAMPLER_COUNT
- };
- enum
- {
- TEXTURE_DMAP,
- TEXTURE_SMAP,
- TEXTURE_COUNT
- };
- constexpr int32_t kNumVec4 = 2;
- struct Uniforms
- {
- void init()
- {
- u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4, kNumVec4);
- cull = 1;
- freeze = 0;
- gpuSubd = 3;
- }
- void submit()
- {
- bgfx::setUniform(u_params, params, kNumVec4);
- }
- void destroy()
- {
- bgfx::destroy(u_params);
- }
- union
- {
- struct
- {
- float dmapFactor;
- float lodFactor;
- float cull;
- float freeze;
- float gpuSubd;
- float padding0;
- float padding1;
- float padding2;
- };
- float params[kNumVec4 * 4];
- };
- bgfx::UniformHandle u_params;
- };
- class ExampleTessellation : public entry::AppI
- {
- public:
- ExampleTessellation(const char* _name, const char* _description, const char* _url)
- : entry::AppI(_name, _description, _url)
- {
- }
- void init(int32_t _argc, const char* const* _argv, uint32_t _width, uint32_t _height) override
- {
- Args args(_argc, _argv);
- m_width = _width;
- m_height = _height;
- m_debug = BGFX_DEBUG_NONE;
- m_reset = BGFX_RESET_NONE;
- bgfx::Init init;
- init.type = args.m_type;
- init.vendorId = args.m_pciId;
- init.resolution.width = m_width;
- init.resolution.height = m_height;
- init.resolution.reset = m_reset;
- bgfx::init(init);
- m_dmap = { "textures/dmap.png", 0.45f };
- m_computeThreadCount = 5;
- m_shading = PROGRAM_TERRAIN;
- m_primitivePixelLengthTarget = 7.0f;
- m_fovy = 60.0f;
- m_pingPong = 0;
- m_restart = true;
- // 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
- );
- bgfx::setViewClear(1
- , BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
- , 0x303030ff
- , 1.0f
- , 0
- );
- // Imgui.
- imguiCreate();
- m_timeOffset = bx::getHPCounter();
- m_oldWidth = 0;
- m_oldHeight = 0;
- m_oldReset = m_reset;
- cameraCreate();
- cameraSetPosition({ 0.0f, 0.5f, 0.0f });
- cameraSetVerticalAngle(0);
- m_wireframe = false;
- m_freeze = false;
- m_cull = true;
- loadPrograms();
- loadBuffers();
- loadTextures();
- createAtomicCounters();
- m_dispatchIndirect = bgfx::createIndirectBuffer(2);
- }
- virtual int shutdown() override
- {
- // Cleanup.
- cameraDestroy();
- imguiDestroy();
- m_uniforms.destroy();
- bgfx::destroy(m_bufferCounter);
- bgfx::destroy(m_bufferCulledSubd);
- bgfx::destroy(m_bufferSubd[0]);
- bgfx::destroy(m_bufferSubd[1]);
- bgfx::destroy(m_dispatchIndirect);
- bgfx::destroy(m_geometryIndices);
- bgfx::destroy(m_geometryVertices);
- bgfx::destroy(m_instancedGeometryIndices);
- bgfx::destroy(m_instancedGeometryVertices);
- for (uint32_t i = 0; i < PROGRAM_COUNT; ++i)
- {
- bgfx::destroy(m_programsCompute[i]);
- }
- for (uint32_t i = 0; i < SHADING_COUNT; ++i)
- {
- bgfx::destroy(m_programsDraw[i]);
- }
- for (uint32_t i = 0; i < SAMPLER_COUNT; ++i)
- {
- bgfx::destroy(m_samplers[i]);
- }
- for (uint32_t i = 0; i < TEXTURE_COUNT; ++i)
- {
- bgfx::destroy(m_textures[i]);
- }
- // Shutdown bgfx.
- bgfx::shutdown();
- return 0;
- }
- bool update() override
- {
- if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
- {
- 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 float deltaTime = float(frameTime / freq);
- 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
- , uint16_t(m_width)
- , uint16_t(m_height)
- );
- showExampleDialog(this);
- ImGui::SetNextWindowPos(
- ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
- , ImGuiCond_FirstUseEver
- );
- ImGui::SetNextWindowSize(
- ImVec2(m_width / 5.0f, m_height / 3.0f)
- , ImGuiCond_FirstUseEver
- );
- ImGui::Begin("Settings", NULL, 0);
- if (ImGui::Checkbox("Debug wireframe", &m_wireframe) )
- {
- bgfx::setDebug(m_wireframe
- ? BGFX_DEBUG_WIREFRAME
- : BGFX_DEBUG_NONE
- );
- }
- ImGui::SameLine();
- if (ImGui::Checkbox("Cull", &m_cull) )
- {
- m_uniforms.cull = m_cull ? 1.0f : 0.0f;
- }
- ImGui::SameLine();
- if (ImGui::Checkbox("Freeze subdividing", &m_freeze) )
- {
- m_uniforms.freeze = m_freeze ? 1.0f : 0.0f;
- }
- ImGui::SliderFloat("Pixels per edge", &m_primitivePixelLengthTarget, 1, 20);
- int gpuSlider = (int)m_uniforms.gpuSubd;
- if (ImGui::SliderInt("Triangle Patch level", &gpuSlider, 0, 3) )
- {
- m_restart = true;
- m_uniforms.gpuSubd = float(gpuSlider);
- }
- ImGui::Combo("Shading", &m_shading, s_shaderOptions, 2);
- ImGui::Text("Some variables require rebuilding the subdivide buffers and causes a stutter.");
- ImGui::End();
- // Update camera.
- cameraUpdate(deltaTime*0.01f, m_mouseState, ImGui::MouseOverArea() );
- bgfx::touch(0);
- bgfx::touch(1);
- configureUniforms();
- cameraGetViewMtx(m_viewMtx);
- float model[16];
- bx::mtxRotateX(model, bx::toRad(90) );
- bx::mtxProj(m_projMtx, m_fovy, float(m_width) / float(m_height), 0.0001f, 2000.0f, bgfx::getCaps()->homogeneousDepth);
- // Set view 0
- bgfx::setViewTransform(0, m_viewMtx, m_projMtx);
- // Set view 1
- bgfx::setViewRect(1, 0, 0, uint16_t(m_width), uint16_t(m_height) );
- bgfx::setViewTransform(1, m_viewMtx, m_projMtx);
- m_uniforms.submit();
- // update the subd buffers
- if (m_restart)
- {
- m_pingPong = 1;
- bgfx::destroy(m_instancedGeometryVertices);
- bgfx::destroy(m_instancedGeometryIndices);
- bgfx::destroy(m_bufferSubd[BUFFER_SUBD]);
- bgfx::destroy(m_bufferSubd[BUFFER_SUBD + 1]);
- bgfx::destroy(m_bufferCulledSubd);
- loadInstancedGeometryBuffers();
- loadSubdivisionBuffers();
- //init indirect
- bgfx::setBuffer(1, m_bufferSubd[m_pingPong], bgfx::Access::ReadWrite);
- bgfx::setBuffer(2, m_bufferCulledSubd, bgfx::Access::ReadWrite);
- bgfx::setBuffer(3, m_dispatchIndirect, bgfx::Access::ReadWrite);
- bgfx::setBuffer(4, m_bufferCounter, bgfx::Access::ReadWrite);
- bgfx::setBuffer(8, m_bufferSubd[1 - m_pingPong], bgfx::Access::ReadWrite);
- bgfx::dispatch(0, m_programsCompute[PROGRAM_INIT_INDIRECT], 1, 1, 1);
- m_restart = false;
- }
- else
- {
- // update batch
- bgfx::setBuffer(3, m_dispatchIndirect, bgfx::Access::ReadWrite);
- bgfx::setBuffer(4, m_bufferCounter, bgfx::Access::ReadWrite);
- bgfx::dispatch(0, m_programsCompute[PROGRAM_UPDATE_INDIRECT], 1, 1, 1);
- }
- bgfx::setBuffer(1, m_bufferSubd[m_pingPong], bgfx::Access::ReadWrite);
- bgfx::setBuffer(2, m_bufferCulledSubd, bgfx::Access::ReadWrite);
- bgfx::setBuffer(4, m_bufferCounter, bgfx::Access::ReadWrite);
- bgfx::setBuffer(6, m_geometryVertices, bgfx::Access::Read);
- bgfx::setBuffer(7, m_geometryIndices, bgfx::Access::Read);
- bgfx::setBuffer(8, m_bufferSubd[1 - m_pingPong], bgfx::Access::Read);
- bgfx::setTransform(model);
- bgfx::setTexture(0, m_samplers[TERRAIN_DMAP_SAMPLER], m_textures[TEXTURE_DMAP], BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
- m_uniforms.submit();
- // update the subd buffer
- bgfx::dispatch(0, m_programsCompute[PROGRAM_SUBD_CS_LOD], m_dispatchIndirect, 1);
- // update draw
- bgfx::setBuffer(3, m_dispatchIndirect, bgfx::Access::ReadWrite);
- bgfx::setBuffer(4, m_bufferCounter, bgfx::Access::ReadWrite);
- m_uniforms.submit();
- bgfx::dispatch(1, m_programsCompute[PROGRAM_UPDATE_DRAW], 1, 1, 1);
- // render the terrain
- bgfx::setTexture(0, m_samplers[TERRAIN_DMAP_SAMPLER], m_textures[TEXTURE_DMAP], BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
- bgfx::setTexture(1, m_samplers[TERRAIN_SMAP_SAMPLER], m_textures[TEXTURE_SMAP], BGFX_SAMPLER_MIN_ANISOTROPIC | BGFX_SAMPLER_MAG_ANISOTROPIC);
- bgfx::setTransform(model);
- bgfx::setVertexBuffer(0, m_instancedGeometryVertices);
- bgfx::setIndexBuffer(m_instancedGeometryIndices);
- bgfx::setBuffer(2, m_bufferCulledSubd, bgfx::Access::Read);
- bgfx::setBuffer(3, m_geometryVertices, bgfx::Access::Read);
- bgfx::setBuffer(4, m_geometryIndices, bgfx::Access::Read);
- bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_Z | BGFX_STATE_DEPTH_TEST_LESS);
- m_uniforms.submit();
- bgfx::submit(1, m_programsDraw[m_shading], m_dispatchIndirect);
- m_pingPong = 1 - m_pingPong;
- imguiEndFrame();
- // Advance to next frame. Rendering thread will be kicked to
- // process submitted rendering primitives.
- bgfx::frame(false);
- return true;
- }
- return false;
- }
- void createAtomicCounters()
- {
- m_bufferCounter = bgfx::createDynamicIndexBuffer(3, BGFX_BUFFER_INDEX32 | BGFX_BUFFER_COMPUTE_READ_WRITE);
- }
- void configureUniforms()
- {
- float lodFactor = 2.0f * bx::tan(bx::toRad(m_fovy) / 2.0f)
- / m_width * (1 << (int)m_uniforms.gpuSubd)
- * m_primitivePixelLengthTarget;
- m_uniforms.lodFactor = lodFactor;
- m_uniforms.dmapFactor = m_dmap.scale;
- }
- /**
- * Load the Terrain Program
- *
- * This program renders an adaptive terrain using the implicit subdivision
- * technique discribed in GPU Zen 2.
- **/
- void loadPrograms()
- {
- m_samplers[TERRAIN_DMAP_SAMPLER] = bgfx::createUniform("u_DmapSampler", bgfx::UniformType::Sampler);
- m_samplers[TERRAIN_SMAP_SAMPLER] = bgfx::createUniform("u_SmapSampler", bgfx::UniformType::Sampler);
- m_uniforms.init();
- m_programsDraw[PROGRAM_TERRAIN] = loadProgram("vs_terrain_render", "fs_terrain_render");
- m_programsDraw[PROGRAM_TERRAIN_NORMAL] = loadProgram("vs_terrain_render", "fs_terrain_render_normal");
- m_programsCompute[PROGRAM_SUBD_CS_LOD] = bgfx::createProgram(loadShader("cs_terrain_lod"), true);
- m_programsCompute[PROGRAM_UPDATE_INDIRECT] = bgfx::createProgram(loadShader("cs_terrain_update_indirect"), true);
- m_programsCompute[PROGRAM_UPDATE_DRAW] = bgfx::createProgram(loadShader("cs_terrain_update_draw"), true);
- m_programsCompute[PROGRAM_INIT_INDIRECT] = bgfx::createProgram(loadShader("cs_terrain_init"), true);
- }
- void loadSmapTexture()
- {
- int w = dmap->m_width;
- int h = dmap->m_height;
- const uint16_t *texels = (const uint16_t *)dmap->m_data;
- int mipcnt = dmap->m_numMips;
- const bgfx::Memory* mem = bgfx::alloc(w * h * 2 * sizeof(float) );
- float* smap = (float*)mem->data;
- for (int j = 0; j < h; ++j)
- {
- for (int i = 0; i < w; ++i)
- {
- int i1 = bx::max(0, i - 1);
- int i2 = bx::min(w - 1, i + 1);
- int j1 = bx::max(0, j - 1);
- int j2 = bx::min(h - 1, j + 1);
- uint16_t px_l = texels[i1 + w * j]; // in [0,2^16-1]
- uint16_t px_r = texels[i2 + w * j]; // in [0,2^16-1]
- uint16_t px_b = texels[i + w * j1]; // in [0,2^16-1]
- uint16_t px_t = texels[i + w * j2]; // in [0,2^16-1]
- float z_l = (float)px_l / 65535.0f; // in [0, 1]
- float z_r = (float)px_r / 65535.0f; // in [0, 1]
- float z_b = (float)px_b / 65535.0f; // in [0, 1]
- float z_t = (float)px_t / 65535.0f; // in [0, 1]
- float slope_x = (float)w * 0.5f * (z_r - z_l);
- float slope_y = (float)h * 0.5f * (z_t - z_b);
- smap[2 * (i + w * j)] = slope_x;
- smap[1 + 2 * (i + w * j)] = slope_y;
- }
- }
- m_textures[TEXTURE_SMAP] = bgfx::createTexture2D(
- (uint16_t)w
- , (uint16_t)h
- , mipcnt > 1
- , 1
- , bgfx::TextureFormat::RG32F
- , BGFX_TEXTURE_NONE
- , mem
- );
- }
- /**
- * Load the Displacement Texture
- *
- * This loads an R16 texture used as a displacement map
- */
- void loadDmapTexture()
- {
- dmap = imageLoad(m_dmap.pathToFile.getCPtr(), bgfx::TextureFormat::R16);
- m_textures[TEXTURE_DMAP] = bgfx::createTexture2D(
- (uint16_t)dmap->m_width
- , (uint16_t)dmap->m_height
- , false
- , 1
- , bgfx::TextureFormat::R16
- , BGFX_TEXTURE_NONE
- , bgfx::makeRef(dmap->m_data, dmap->m_size)
- );
- }
- /**
- * Load All Textures
- */
- void loadTextures()
- {
- loadDmapTexture();
- loadSmapTexture();
- }
- /**
- * Load the Geometry Buffer
- *
- * This procedure loads the scene geometry into an index and
- * vertex buffer. Here, we only load 2 triangles to define the
- * terrain.
- **/
- void loadGeometryBuffers()
- {
- const float vertices[] =
- {
- -1.0f, -1.0f, 0.0f, 1.0f,
- +1.0f, -1.0f, 0.0f, 1.0f,
- +1.0f, +1.0f, 0.0f, 1.0f,
- -1.0f, +1.0f, 0.0f, 1.0f,
- };
- const uint32_t indices[] = { 0, 1, 3, 2, 3, 1 };
- m_geometryLayout.begin().add(bgfx::Attrib::Position, 4, bgfx::AttribType::Float).end();
- m_geometryVertices = bgfx::createVertexBuffer(
- bgfx::copy(vertices, sizeof(vertices) )
- , m_geometryLayout
- , BGFX_BUFFER_COMPUTE_READ
- );
- m_geometryIndices = bgfx::createIndexBuffer(
- bgfx::copy(indices, sizeof(indices) )
- , BGFX_BUFFER_COMPUTE_READ | BGFX_BUFFER_INDEX32
- );
- }
- void loadSubdivisionBuffers()
- {
- const uint32_t bufferCapacity = 1 << 27;
- m_bufferSubd[BUFFER_SUBD] = bgfx::createDynamicIndexBuffer(
- bufferCapacity
- , BGFX_BUFFER_COMPUTE_READ_WRITE | BGFX_BUFFER_INDEX32
- );
- m_bufferSubd[BUFFER_SUBD + 1] = bgfx::createDynamicIndexBuffer(
- bufferCapacity
- , BGFX_BUFFER_COMPUTE_READ_WRITE | BGFX_BUFFER_INDEX32
- );
- m_bufferCulledSubd = bgfx::createDynamicIndexBuffer(
- bufferCapacity
- , BGFX_BUFFER_COMPUTE_READ_WRITE | BGFX_BUFFER_INDEX32
- );
- }
- /**
- * Load All Buffers
- *
- */
- void loadBuffers()
- {
- loadSubdivisionBuffers();
- loadGeometryBuffers();
- loadInstancedGeometryBuffers();
- }
- /**
- * This will be used to instantiate a triangle grid for each subdivision
- * key present in the subd buffer.
- */
- void loadInstancedGeometryBuffers()
- {
- const float* vertices;
- const uint32_t* indexes;
- switch (int32_t(m_uniforms.gpuSubd) )
- {
- case 0:
- m_instancedMeshVertexCount = 3;
- m_instancedMeshPrimitiveCount = 1;
- vertices = s_verticesL0;
- indexes = s_indexesL0;
- break;
- case 1:
- m_instancedMeshVertexCount = 6;
- m_instancedMeshPrimitiveCount = 4;
- vertices = s_verticesL1;
- indexes = s_indexesL1;
- break;
- case 2:
- m_instancedMeshVertexCount = 15;
- m_instancedMeshPrimitiveCount = 16;
- vertices = s_verticesL2;
- indexes = s_indexesL2;
- break;
- default:
- m_instancedMeshVertexCount = 45;
- m_instancedMeshPrimitiveCount = 64;
- vertices = s_verticesL3;
- indexes = s_indexesL3;
- break;
- }
- m_instancedGeometryLayout
- .begin()
- .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
- .end();
- m_instancedGeometryVertices = bgfx::createVertexBuffer(
- bgfx::makeRef(vertices, sizeof(float) * 2 * m_instancedMeshVertexCount)
- , m_instancedGeometryLayout
- );
- m_instancedGeometryIndices = bgfx::createIndexBuffer(
- bgfx::makeRef(indexes, sizeof(uint32_t) * m_instancedMeshPrimitiveCount * 3)
- , BGFX_BUFFER_INDEX32
- );
- }
- Uniforms m_uniforms;
- bgfx::ProgramHandle m_programsCompute[PROGRAM_COUNT];
- bgfx::ProgramHandle m_programsDraw[SHADING_COUNT];
- bgfx::TextureHandle m_textures[TEXTURE_COUNT];
- bgfx::UniformHandle m_samplers[SAMPLER_COUNT];
- bgfx::DynamicIndexBufferHandle m_bufferSubd[2];
- bgfx::DynamicIndexBufferHandle m_bufferCulledSubd;
- bgfx::DynamicIndexBufferHandle m_bufferCounter;
- bgfx::IndexBufferHandle m_geometryIndices;
- bgfx::VertexBufferHandle m_geometryVertices;
- bgfx::VertexLayout m_geometryLayout;
- bgfx::IndexBufferHandle m_instancedGeometryIndices;
- bgfx::VertexBufferHandle m_instancedGeometryVertices;
- bgfx::VertexLayout m_instancedGeometryLayout;
- bgfx::IndirectBufferHandle m_dispatchIndirect;
- bimg::ImageContainer* dmap;
- float m_viewMtx[16];
- float m_projMtx[16];
- uint32_t m_width;
- uint32_t m_height;
- uint32_t m_debug;
- uint32_t m_reset;
- uint32_t m_oldWidth;
- uint32_t m_oldHeight;
- uint32_t m_oldReset;
- uint32_t m_instancedMeshVertexCount;
- uint32_t m_instancedMeshPrimitiveCount;
- entry::MouseState m_mouseState;
- int64_t m_timeOffset;
- struct DMap
- {
- bx::FilePath pathToFile;
- float scale;
- };
- DMap m_dmap;
- int m_computeThreadCount;
- int m_shading;
- int m_gpuSubd;
- int m_pingPong;
- float m_primitivePixelLengthTarget;
- float m_fovy;
- bool m_restart;
- bool m_wireframe;
- bool m_cull;
- bool m_freeze;
- };
- } // namespace
- ENTRY_IMPLEMENT_MAIN(
- ExampleTessellation
- , "41-tess"
- , "Adaptive GPU Tessellation."
- , "https://bkaradzic.github.io/bgfx/examples.html#tess"
- );
|