void submit(bgfx::ProgramHandle _program, float* _mtx, bool _blend) { for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it) { const Group& group = *it; // Set model matrix for rendering. bgfx::setTransform(_mtx); bgfx::setProgram(_program); bgfx::setIndexBuffer(group.m_ibh); bgfx::setVertexBuffer(group.m_vbh); // Set render states. bgfx::setState(0 |BGFX_STATE_RGB_WRITE |BGFX_STATE_ALPHA_WRITE |(_blend?0:BGFX_STATE_DEPTH_WRITE) |BGFX_STATE_DEPTH_TEST_LESS |BGFX_STATE_CULL_CCW |BGFX_STATE_MSAA |(_blend?BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA):0) ); // Submit primitive for rendering to view 0. bgfx::submit(0); } }
void render(ImDrawData* _drawData) { const ImGuiIO& io = ImGui::GetIO(); const float width = io.DisplaySize.x; const float height = io.DisplaySize.y; bgfx::setViewName(m_viewId, "ImGui"); bgfx::setViewMode(m_viewId, bgfx::ViewMode::Sequential); const bgfx::HMD* hmd = bgfx::getHMD(); const bgfx::Caps* caps = bgfx::getCaps(); if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) ) { float proj[16]; bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f, bgfx::getCaps()->homogeneousDepth); static float time = 0.0f; time += 0.05f; const float dist = 10.0f; const float offset0 = -proj[8] + (hmd->eye[0].viewOffset[0] / dist * proj[0]); const float offset1 = -proj[8] + (hmd->eye[1].viewOffset[0] / dist * proj[0]); float ortho[2][16]; const float viewOffset = width/4.0f; const float viewWidth = width/2.0f; bx::mtxOrtho(ortho[0], viewOffset, viewOffset + viewWidth, height, 0.0f, 0.0f, 1000.0f, offset0, caps->homogeneousDepth); bx::mtxOrtho(ortho[1], viewOffset, viewOffset + viewWidth, height, 0.0f, 0.0f, 1000.0f, offset1, caps->homogeneousDepth); bgfx::setViewTransform(m_viewId, NULL, ortho[0], BGFX_VIEW_STEREO, ortho[1]); bgfx::setViewRect(m_viewId, 0, 0, hmd->width, hmd->height); } else { float ortho[16]; bx::mtxOrtho(ortho, 0.0f, width, height, 0.0f, 0.0f, 1000.0f, 0.0f, caps->homogeneousDepth); bgfx::setViewTransform(m_viewId, NULL, ortho); bgfx::setViewRect(m_viewId, 0, 0, uint16_t(width), uint16_t(height) ); } // Render command lists for (int32_t ii = 0, num = _drawData->CmdListsCount; ii < num; ++ii) { bgfx::TransientVertexBuffer tvb; bgfx::TransientIndexBuffer tib; const ImDrawList* drawList = _drawData->CmdLists[ii]; uint32_t numVertices = (uint32_t)drawList->VtxBuffer.size(); uint32_t numIndices = (uint32_t)drawList->IdxBuffer.size(); if (!checkAvailTransientBuffers(numVertices, m_decl, numIndices) ) { // not enough space in transient buffer just quit drawing the rest... break; } bgfx::allocTransientVertexBuffer(&tvb, numVertices, m_decl); bgfx::allocTransientIndexBuffer(&tib, numIndices); ImDrawVert* verts = (ImDrawVert*)tvb.data; bx::memCopy(verts, drawList->VtxBuffer.begin(), numVertices * sizeof(ImDrawVert) ); ImDrawIdx* indices = (ImDrawIdx*)tib.data; bx::memCopy(indices, drawList->IdxBuffer.begin(), numIndices * sizeof(ImDrawIdx) ); uint32_t offset = 0; for (const ImDrawCmd* cmd = drawList->CmdBuffer.begin(), *cmdEnd = drawList->CmdBuffer.end(); cmd != cmdEnd; ++cmd) { if (cmd->UserCallback) { cmd->UserCallback(drawList, cmd); } else if (0 != cmd->ElemCount) { uint64_t state = 0 | BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_MSAA ; bgfx::TextureHandle th = m_texture; bgfx::ProgramHandle program = m_program; if (NULL != cmd->TextureId) { union { ImTextureID ptr; struct { bgfx::TextureHandle handle; uint8_t flags; uint8_t mip; } s; } texture = { cmd->TextureId }; state |= 0 != (IMGUI_FLAGS_ALPHA_BLEND & texture.s.flags) ? BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) : BGFX_STATE_NONE ; th = texture.s.handle; if (0 != texture.s.mip) { const float lodEnabled[4] = { float(texture.s.mip), 1.0f, 0.0f, 0.0f }; bgfx::setUniform(u_imageLodEnabled, lodEnabled); program = m_imageProgram; } } else { state |= BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA); } const uint16_t xx = uint16_t(bx::fmax(cmd->ClipRect.x, 0.0f) ); const uint16_t yy = uint16_t(bx::fmax(cmd->ClipRect.y, 0.0f) ); bgfx::setScissor(xx, yy , uint16_t(bx::fmin(cmd->ClipRect.z, 65535.0f)-xx) , uint16_t(bx::fmin(cmd->ClipRect.w, 65535.0f)-yy) ); bgfx::setState(state); bgfx::setTexture(0, s_tex, th); bgfx::setVertexBuffer(0, &tvb, 0, numVertices); bgfx::setIndexBuffer(&tib, offset, cmd->ElemCount); bgfx::submit(cmd->ViewId, program); } offset += cmd->ElemCount; } } }
void render(ImDrawData* draw_data) { const float width = ImGui::GetIO().DisplaySize.x; const float height = ImGui::GetIO().DisplaySize.y; float ortho[16]; bx::mtxOrtho(ortho, 0.0f, width, height, 0.0f, -1.0f, 1.0f); bgfx::setViewTransform(m_viewId, NULL, ortho); // Render command lists for (int32_t ii = 0; ii < draw_data->CmdListsCount; ++ii) { bgfx::TransientVertexBuffer tvb; bgfx::TransientIndexBuffer tib; const ImDrawList* cmd_list = draw_data->CmdLists[ii]; uint32_t vtx_size = (uint32_t)cmd_list->VtxBuffer.size(); uint32_t idx_size = (uint32_t)cmd_list->IdxBuffer.size(); if (!bgfx::checkAvailTransientVertexBuffer(vtx_size, m_decl) || !bgfx::checkAvailTransientIndexBuffer(idx_size) ) { // not enough space in transient buffer just quit drawing the rest... break; } bgfx::allocTransientVertexBuffer(&tvb, vtx_size, m_decl); bgfx::allocTransientIndexBuffer(&tib, idx_size); ImDrawVert* verts = (ImDrawVert*)tvb.data; memcpy(verts, cmd_list->VtxBuffer.begin(), vtx_size * sizeof(ImDrawVert) ); ImDrawIdx* indices = (ImDrawIdx*)tib.data; memcpy(indices, cmd_list->IdxBuffer.begin(), idx_size * sizeof(ImDrawIdx) ); uint32_t elem_offset = 0; const ImDrawCmd* pcmd_begin = cmd_list->CmdBuffer.begin(); const ImDrawCmd* pcmd_end = cmd_list->CmdBuffer.end(); for (const ImDrawCmd* pcmd = pcmd_begin; pcmd != pcmd_end; pcmd++) { if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); elem_offset += pcmd->ElemCount; continue; } if (0 == pcmd->ElemCount) { continue; } bgfx::setState(0 | BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) | BGFX_STATE_MSAA ); bgfx::setScissor(uint16_t(bx::fmax(pcmd->ClipRect.x, 0.0f) ) , uint16_t(bx::fmax(pcmd->ClipRect.y, 0.0f) ) , uint16_t(bx::fmin(pcmd->ClipRect.z, 65535.0f)-bx::fmax(pcmd->ClipRect.x, 0.0f) ) , uint16_t(bx::fmin(pcmd->ClipRect.w, 65535.0f)-bx::fmax(pcmd->ClipRect.y, 0.0f) ) ); union { void* ptr; bgfx::TextureHandle handle; } texture = { pcmd->TextureId }; bgfx::setTexture(0, s_tex, 0 != texture.handle.idx ? texture.handle : m_texture ); bgfx::setVertexBuffer(&tvb, 0, vtx_size); bgfx::setIndexBuffer(&tib, elem_offset, pcmd->ElemCount); bgfx::setProgram(m_program); bgfx::submit(m_viewId); elem_offset += pcmd->ElemCount; } } }
int _main_(int /*_argc*/, char** /*_argv*/) { // Create vertex stream declaration. PosColorVertex::init(); PosColorTexCoord0Vertex::init(); uint32_t width = 1280; uint32_t height = 720; uint32_t debug = BGFX_DEBUG_TEXT; uint32_t reset = BGFX_RESET_VSYNC; bgfx::init(); bgfx::reset(width, height, reset); // Enable debug text. bgfx::setDebug(debug); // Get renderer capabilities info. const bgfx::Caps* caps = bgfx::getCaps(); // Setup root path for binary shaders. Shader binaries are different // for each renderer. switch (caps->rendererType) { default: break; case bgfx::RendererType::OpenGL: case bgfx::RendererType::OpenGLES: s_flipV = true; break; } // Imgui. void* data = load("font/droidsans.ttf"); imguiCreate(data); free(data); const bgfx::Memory* mem; // Create static vertex buffer. mem = bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) ); bgfx::VertexBufferHandle vbh = bgfx::createVertexBuffer(mem, PosColorVertex::ms_decl); // 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_texColor0 = bgfx::createUniform("u_texColor0", bgfx::UniformType::Uniform1iv); bgfx::UniformHandle u_texColor1 = bgfx::createUniform("u_texColor1", bgfx::UniformType::Uniform1iv); bgfx::UniformHandle u_color = bgfx::createUniform("u_color", bgfx::UniformType::Uniform4fv); bgfx::ProgramHandle blend = loadProgram("vs_oit", "fs_oit" ); bgfx::ProgramHandle wbSeparatePass = loadProgram("vs_oit", "fs_oit_wb_separate" ); bgfx::ProgramHandle wbSeparateBlit = loadProgram("vs_oit_blit", "fs_oit_wb_separate_blit" ); bgfx::ProgramHandle wbPass = loadProgram("vs_oit", "fs_oit_wb" ); bgfx::ProgramHandle wbBlit = loadProgram("vs_oit_blit", "fs_oit_wb_blit" ); bgfx::TextureHandle fbtextures[2] = { BGFX_INVALID_HANDLE, BGFX_INVALID_HANDLE }; bgfx::FrameBufferHandle fbh = BGFX_INVALID_HANDLE; int64_t timeOffset = bx::getHPCounter(); uint32_t mode = 1; int32_t scrollArea = 0; bool frontToBack = true; bool fadeInOut = false; uint32_t oldWidth = 0; uint32_t oldHeight = 0; uint32_t oldReset = reset; entry::MouseState mouseState; while (!entry::processEvents(width, height, debug, reset, &mouseState) ) { if (oldWidth != width || oldHeight != height || oldReset != reset || !bgfx::isValid(fbh) ) { // Recreate variable size render targets when resolution changes. oldWidth = width; oldHeight = height; oldReset = reset; if (bgfx::isValid(fbh) ) { bgfx::destroyFrameBuffer(fbh); } fbtextures[0] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::RGBA16F, BGFX_TEXTURE_RT); fbtextures[1] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::R16F, BGFX_TEXTURE_RT); fbh = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true); } imguiBeginFrame(mouseState.m_mx , mouseState.m_my , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0) | (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0) , 0 , width , height ); imguiBeginScrollArea("Settings", width - width / 4 - 10, 10, width / 4, height / 3, &scrollArea); imguiSeparatorLine(); imguiLabel("Blend mode:"); mode = imguiChoose(mode , "None" , "Separate" , "MRT Independent" ); imguiSeparatorLine(); if (imguiCheck("Front to back", frontToBack) ) { frontToBack ^= true; } if (imguiCheck("Fade in/out", fadeInOut) ) { fadeInOut ^= true; } imguiEndScrollArea(); imguiEndFrame(); // Set view 0 default viewport. bgfx::setViewRectMask(0x3, 0, 0, width, height); 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; float time = (float)( (now-timeOffset)/freq); // Use debug font to print information about this example. bgfx::dbgTextClear(); // Reference: // Weighted, Blended Order-Independent Transparency // http://jcgt.org/published/0002/02/09/ // http://casual-effects.blogspot.com/2014/03/weighted-blended-order-independent.html bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/19-oit"); bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Weighted, Blended Order Independent Transparency."); bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs); float at[3] = { 0.0f, 0.0f, 0.0f }; float eye[3] = { 0.0f, 0.0f, -7.0f }; float view[16]; float proj[16]; // Set view and projection matrix for view 0. bx::mtxLookAt(view, eye, at); bx::mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f); bgfx::setViewTransform(0, view, proj); bgfx::setViewClearMask(0x3 , BGFX_CLEAR_COLOR_BIT|BGFX_CLEAR_DEPTH_BIT , 0x00000000 , 1.0f , 0 ); bgfx::FrameBufferHandle invalid = BGFX_INVALID_HANDLE; bgfx::setViewFrameBuffer(0, 0 == mode ? invalid : fbh); // Set view and projection matrix for view 1. bx::mtxIdentity(view); bx::mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f); bgfx::setViewTransform(1, view, proj); for (uint32_t depth = 0; depth < 3; ++depth) { uint32_t zz = frontToBack ? 2-depth : depth; for (uint32_t yy = 0; yy < 3; ++yy) { for (uint32_t xx = 0; xx < 3; ++xx) { float color[4] = { xx*1.0f/3.0f, zz*1.0f/3.0f, yy*1.0f/3.0f, 0.5f }; if (fadeInOut && zz == 1) { color[3] = sinf(time*3.0f)*0.49f+0.5f; } bgfx::setUniform(u_color, color); BX_UNUSED(time); float mtx[16]; bx::mtxRotateXY(mtx, time*0.023f + xx*0.21f, time*0.03f + yy*0.37f); //mtxIdentity(mtx); mtx[12] = -2.5f + float(xx)*2.5f; mtx[13] = -2.5f + float(yy)*2.5f; mtx[14] = -2.5f + float(zz)*2.5f; //0.0f; // sinf(time + ( (xx+1)*(yy+1)/9.0f)*float(M_PI) )*50.0f+50.0f; //90.0f - (xx+1)*(yy+1)*10.0f; // Set transform for draw call. bgfx::setTransform(mtx); // Set vertex and index buffer. bgfx::setVertexBuffer(vbh); bgfx::setIndexBuffer(ibh); const uint64_t state = 0 | BGFX_STATE_CULL_CW | BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_DEPTH_TEST_LESS | BGFX_STATE_MSAA ; switch (mode) { case 0: // Set vertex and fragment shaders. bgfx::setProgram(blend); // Set render states. bgfx::setState(state | BGFX_STATE_BLEND_ALPHA ); break; case 1: // Set vertex and fragment shaders. bgfx::setProgram(wbSeparatePass); // Set render states. bgfx::setState(state | BGFX_STATE_BLEND_FUNC_SEPARATE(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ZERO, BGFX_STATE_BLEND_INV_SRC_ALPHA) ); break; default: // Set vertex and fragment shaders. bgfx::setProgram(wbPass); // Set render states. bgfx::setState(state | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE) | BGFX_STATE_BLEND_INDEPENDENT , 0 | BGFX_STATE_BLEND_FUNC_RT_1(BGFX_STATE_BLEND_ZERO, BGFX_STATE_BLEND_SRC_COLOR) ); break; } // Submit primitive for rendering to view 0. bgfx::submit(0); } } } if (0 != mode) { bgfx::setTexture(0, u_texColor0, fbtextures[0]); bgfx::setTexture(1, u_texColor1, fbtextures[1]); bgfx::setProgram(1 == mode ? wbSeparateBlit : wbBlit); bgfx::setState(0 | BGFX_STATE_RGB_WRITE | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_INV_SRC_ALPHA, BGFX_STATE_BLEND_SRC_ALPHA) ); screenSpaceQuad( (float)width, (float)height, s_flipV); bgfx::submit(1); } // Advance to next frame. Rendering thread will be kicked to // process submitted rendering primitives. bgfx::frame(); } // Cleanup. imguiDestroy(); bgfx::destroyFrameBuffer(fbh); bgfx::destroyIndexBuffer(ibh); bgfx::destroyVertexBuffer(vbh); bgfx::destroyProgram(blend); bgfx::destroyProgram(wbSeparatePass); bgfx::destroyProgram(wbSeparateBlit); bgfx::destroyProgram(wbPass); bgfx::destroyProgram(wbBlit); bgfx::destroyUniform(u_texColor0); bgfx::destroyUniform(u_texColor1); bgfx::destroyUniform(u_color); // Shutdown bgfx. bgfx::shutdown(); return 0; }
void render(ImDrawData* _drawData) { const ImGuiIO& io = ImGui::GetIO(); const float width = io.DisplaySize.x; const float height = io.DisplaySize.y; { float ortho[16]; bx::mtxOrtho(ortho, 0.0f, width, height, 0.0f, -1.0f, 1.0f); bgfx::setViewTransform(m_viewId, NULL, ortho); } #if USE_ENTRY for (uint32_t ii = 1; ii < BX_COUNTOF(m_window); ++ii) { Window& window = m_window[ii]; if (bgfx::isValid(window.m_fbh) ) { const uint8_t viewId = window.m_viewId; bgfx::setViewClear(viewId , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH , 0x303030ff , 1.0f , 0 ); bgfx::setViewFrameBuffer(viewId, window.m_fbh); bgfx::setViewRect(viewId , 0 , 0 , window.m_state.m_width , window.m_state.m_height ); float ortho[16]; bx::mtxOrtho(ortho , 0.0f , float(window.m_state.m_width) , float(window.m_state.m_height) , 0.0f , -1.0f , 1.0f ); bgfx::setViewTransform(viewId , NULL , ortho ); } } #endif // USE_ENTRY // Render command lists for (int32_t ii = 0, num = _drawData->CmdListsCount; ii < num; ++ii) { bgfx::TransientVertexBuffer tvb; bgfx::TransientIndexBuffer tib; const ImDrawList* drawList = _drawData->CmdLists[ii]; uint32_t numVertices = (uint32_t)drawList->VtxBuffer.size(); uint32_t numIndices = (uint32_t)drawList->IdxBuffer.size(); if (!bgfx::checkAvailTransientVertexBuffer(numVertices, m_decl) || !bgfx::checkAvailTransientIndexBuffer(numIndices) ) { // not enough space in transient buffer just quit drawing the rest... break; } bgfx::allocTransientVertexBuffer(&tvb, numVertices, m_decl); bgfx::allocTransientIndexBuffer(&tib, numIndices); ImDrawVert* verts = (ImDrawVert*)tvb.data; memcpy(verts, drawList->VtxBuffer.begin(), numVertices * sizeof(ImDrawVert) ); ImDrawIdx* indices = (ImDrawIdx*)tib.data; memcpy(indices, drawList->IdxBuffer.begin(), numIndices * sizeof(ImDrawIdx) ); uint32_t offset = 0; for (const ImDrawCmd* cmd = drawList->CmdBuffer.begin(), *cmdEnd = drawList->CmdBuffer.end(); cmd != cmdEnd; ++cmd) { if (cmd->UserCallback) { cmd->UserCallback(drawList, cmd); } else if (0 != cmd->ElemCount) { uint64_t state = 0 | BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_MSAA ; bgfx::TextureHandle th = m_texture; bgfx::ProgramHandle program = m_program; if (NULL != cmd->TextureId) { union { ImTextureID ptr; struct { bgfx::TextureHandle handle; uint8_t flags; uint8_t mip; } s; } texture = { cmd->TextureId }; state |= 0 != (IMGUI_FLAGS_ALPHA_BLEND & texture.s.flags) ? BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) : BGFX_STATE_NONE ; th = texture.s.handle; if (0 != texture.s.mip) { extern bgfx::ProgramHandle imguiGetImageProgram(uint8_t _mip); program = imguiGetImageProgram(texture.s.mip); } } else { state |= BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA); } const uint16_t xx = uint16_t(bx::fmax(cmd->ClipRect.x, 0.0f) ); const uint16_t yy = uint16_t(bx::fmax(cmd->ClipRect.y, 0.0f) ); bgfx::setScissor(xx, yy , uint16_t(bx::fmin(cmd->ClipRect.z, 65535.0f)-xx) , uint16_t(bx::fmin(cmd->ClipRect.w, 65535.0f)-yy) ); bgfx::setState(state); bgfx::setTexture(0, s_tex, th); bgfx::setVertexBuffer(&tvb, 0, numVertices); bgfx::setIndexBuffer(&tib, offset, cmd->ElemCount); bgfx::submit(cmd->ViewId, program); } offset += cmd->ElemCount; } } }
void QuadRenderer::submit() { if (quadCount <= 0) { return; } numFrameSubmit++; if (Texture::sTextureInfos[currentTexture].handle.idx != MARKEDTEXTURE) { // On iPad 1, the PosColorTex shader, which multiplies texture color with // vertex color, is 5x slower than PosTex, which just draws the texture // unmodified. So we do this. if(sTinted) bgfx::setProgram(sProgramPosColorTex); else bgfx::setProgram(sProgramPosTex); lmAssert(sIndexBufferHandle.idx != bgfx::invalidHandle, "No index buffer!"); bgfx::setIndexBuffer(sIndexBufferHandle, currentIndexBufferIdx, (quadCount * 6)); bgfx::setVertexBuffer(vertexBuffers[currentVertexBufferIdx], MAXBATCHQUADS * 4); // set U and V wrap modes (repeat / mirror / clamp) uint32_t textureFlags = BGFX_TEXTURE_W_CLAMP; ///U switch(Texture::sTextureInfos[currentTexture].wrapU) { case TEXTUREINFO_WRAP_REPEAT: textureFlags |= BGFX_TEXTURE_NONE; break; case TEXTUREINFO_WRAP_MIRROR: textureFlags |= BGFX_TEXTURE_U_MIRROR; break; case TEXTUREINFO_WRAP_CLAMP: textureFlags |= BGFX_TEXTURE_U_CLAMP; break; } ///V switch(Texture::sTextureInfos[currentTexture].wrapV) { case TEXTUREINFO_WRAP_REPEAT: textureFlags |= BGFX_TEXTURE_NONE; break; case TEXTUREINFO_WRAP_MIRROR: textureFlags |= BGFX_TEXTURE_V_MIRROR; break; case TEXTUREINFO_WRAP_CLAMP: textureFlags |= BGFX_TEXTURE_V_CLAMP; break; } // set smoothing mode, bgfx default is bilinear switch (Texture::sTextureInfos[currentTexture].smoothing) { // use nearest neighbor case TEXTUREINFO_SMOOTHING_NONE: textureFlags |= BGFX_TEXTURE_MIN_POINT; textureFlags |= BGFX_TEXTURE_MAG_POINT; textureFlags |= BGFX_TEXTURE_MIP_POINT; break; } bgfx::setTexture(0, sUniformTexColor, Texture::sTextureInfos[currentTexture].handle, textureFlags); // Set render states. bgfx::setState(0 | BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE //|BGFX_STATE_DEPTH_WRITE //|BGFX_STATE_DEPTH_TEST_LESS | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) ); bgfx::submit(Graphics::getView()); currentIndexBufferIdx += quadCount * 6; } quadCount = 0; }
void render(ImDrawList** const _lists, int _count) { const float width = ImGui::GetIO().DisplaySize.x; const float height = ImGui::GetIO().DisplaySize.y; float ortho[16]; bx::mtxOrtho(ortho, 0.0f, width, height, 0.0f, -1.0f, 1.0f); bgfx::setViewTransform(m_viewId, NULL, ortho); // Render command lists for (int32_t ii = 0; ii < _count; ++ii) { bgfx::TransientVertexBuffer tvb; uint32_t vtx_size = 0; const ImDrawList* cmd_list = _lists[ii]; const ImDrawVert* vtx_buffer = cmd_list->vtx_buffer.begin(); const ImDrawCmd* pcmd_begin = cmd_list->commands.begin(); const ImDrawCmd* pcmd_end = cmd_list->commands.end(); for (const ImDrawCmd* pcmd = pcmd_begin; pcmd != pcmd_end; pcmd++) { vtx_size += (uint32_t)pcmd->vtx_count; } if (!bgfx::checkAvailTransientVertexBuffer(vtx_size, m_decl)) { // not enough space in transient buffer just quit drawing the rest... break; } bgfx::allocTransientVertexBuffer(&tvb, vtx_size, m_decl); ImDrawVert* verts = (ImDrawVert*)tvb.data; memcpy(verts, vtx_buffer, vtx_size * sizeof(ImDrawVert)); uint32_t vtx_offset = 0; for (const ImDrawCmd* pcmd = pcmd_begin; pcmd != pcmd_end; pcmd++) { bgfx::setState(0 | BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) | BGFX_STATE_MSAA ); bgfx::setScissor(uint16_t(pcmd->clip_rect.x) , uint16_t(pcmd->clip_rect.y) , uint16_t(pcmd->clip_rect.z-pcmd->clip_rect.x) , uint16_t(pcmd->clip_rect.w-pcmd->clip_rect.y) ); union { void* ptr; bgfx::TextureHandle handle; } texture = { pcmd->texture_id }; bgfx::setTexture(0, s_tex, 0 != texture.handle.idx ? texture.handle : m_texture ); bgfx::setVertexBuffer(&tvb, vtx_offset, pcmd->vtx_count); bgfx::setProgram(m_program); bgfx::submit(m_viewId); vtx_offset += pcmd->vtx_count; } } }