// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // If text or lines are blurry when integrating ImGui in your engine: // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data) { // Backup GL state GLint last_program, last_texture, last_array_buffer, last_element_array_buffer; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glActiveTexture(GL_TEXTURE0); // Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays) ImGuiIO& io = ImGui::GetIO(); float fb_height = io.DisplaySize.y * io.DisplayFramebufferScale.y; draw_data->ScaleClipRects(io.DisplayFramebufferScale); // Setup orthographic projection matrix const float ortho_projection[4][4] = { { 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f }, { 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f }, { 0.0f, 0.0f, -1.0f, 0.0f }, {-1.0f, 1.0f, 0.0f, 1.0f }, }; glUseProgram(g_ShaderHandle); glUniform1i(g_AttribLocationTex, 0); glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); // Render command lists glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); glEnableVertexAttribArray(g_AttribLocationPosition); glEnableVertexAttribArray(g_AttribLocationUV); glEnableVertexAttribArray(g_AttribLocationColor); #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); #undef OFFSETOF for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawIdx* idx_buffer_offset = 0; glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.size() * sizeof(ImDrawVert), (GLvoid*)&cmd_list->VtxBuffer.front(), GL_STREAM_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx), (GLvoid*)&cmd_list->IdxBuffer.front(), GL_STREAM_DRAW); for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) { if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer_offset); } idx_buffer_offset += pcmd->ElemCount; } } // Restore modified state glDisableVertexAttribArray(g_AttribLocationPosition); glDisableVertexAttribArray(g_AttribLocationUV); glDisableVertexAttribArray(g_AttribLocationColor); glUseProgram(last_program); glBindTexture(GL_TEXTURE_2D, last_texture); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer); glDisable(GL_SCISSOR_TEST); }
bool KRenderSys::update(F64 Delta) { // update all active camera(s) (sorted) for (auto camit = _kcamList.begin(); camit != _kcamList.end(); ++camit) { auto cam = (*camit); // skip inactive camera if (!cam->getOwnerNode()->isActive()) continue; _kupdata.clear(); // check active if (entity->isActive()) { // check render target (texture or screen) if (cam->getRenderTexture()) { _kfbo->bind(); auto tarray = static_cast<KAtlasTextureArray *>(cam->getRenderTexture().get()); _initeFrameBuffer(tarray, cam->getRenderTextureIndex()); } else { _kfbo->unbind(); DGL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); } // update viewport and scissor if (_klastState.lastViewSize != cam->_ksize || _klastState.lastViewPos != cam->_kposition) { DGL_CALL(glViewport(cam->_kposition.x, cam->_kposition.y, cam->_ksize.x, cam->_ksize.y)); _klastState.lastViewSize = cam->_ksize; _klastState.lastViewPos = cam->_kposition; DGL_CALL(glScissor(cam->_kposition.x, cam->_kposition.y, cam->_ksize.x, cam->_ksize.y)); } // update clear color if (cam->_kclearCol != _klastState.lastColor) { DGL_CALL(glClearColor((GLclampf)(cam->_kclearCol.getGLR()), (GLclampf)(cam->_kclearCol.getGLG()), (GLclampf)(cam->_kclearCol.getGLB()), (GLclampf)(cam->_kclearCol.getGLA()))); _klastState.lastColor = cam->_kclearCol; } // clear scene if (cam->_kclearView) { DGL_CALL(glClear(GL_COLOR_BUFFER_BIT)); } U32 indSize = 0; U32 verSize = 0; KRenderable *material = nullptr; ED_STATIC std::vector<std::pair<KEntity *, KRenderable *>> objList; objList.reserve(_kconfig.objectSize); // update and draw renderables // culling is enabled if (_kconfig.culling) { const U8 filter = (U8)GCullingObjectsFilter::TILE | (U8)GCullingObjectsFilter::DYNAMIC | (U8)GCullingObjectsFilter::STATIC; _kcullSys->queryObjects(cam, (GCullingObjectsFilter)filter, EManager, objList); } else { // culling is disabled _fillRenderList(EManager, objList); } // sort objects if (_kconfig.zSorting) { // sort using a lambda expression std::sort(objList.begin(), objList.end(), [](const std::pair<KEntity *, KRenderable *> &A, const std::pair<KEntity *, KRenderable *> &B) { return B.first->getZOrder() < A.first->getZOrder(); }); } // render objects list for (auto oit = objList.begin(); oit != objList.end(); ++oit){ auto ent = oit->first; // inite materials if (oit->second->getMatNeedUpdate()) { if (!_initeMaterials(oit->second)) { KD_FPRINT("cant init material. entity name: %s", ent->getName().c_str()); return false; } } // inite state if (oit == objList.begin()) { _checkState(oit->second); } // check material (render shared materials in a single batch) if (_checkState(oit->second)) { // check available buffer size if ((indSize + oit->second->getIndexSize()) < _kconfig.indexSize) { // compute (parent * child * camera) matrix // catch object with its matrix auto trcom = (KTransformCom *)ent->getComponent(CTypes::Transform, ""); _kupdata.matrix.push_back((*cam).getRatioMatrix(trcom->getRatioIndex())); _computeParentsTransform(EManager, ent, &_kupdata.matrix.back()); _kupdata.objects.push_back(oit->second); material = oit->second; // increase buffers size indSize += oit->second->getIndexSize(); verSize += oit->second->getVertex()->size(); // check next object if any if (oit != --objList.end()) { continue; } } } else { --oit; } // render if (!_kupdata.objects.empty()) { // update vetex _kvboVer->update(0, sizeof(KGLVertex) * verSize, false, (void *)&_kupdata); // bind quad vao _kvao->bind(); // bind materials material->getShaderProg()->bind(); auto atlas = material->getATextureArray(); if (atlas) { if (atlas->isInite()) { atlas->bind(); } else { KAtlasTextureArray::unbindTextureArray(); } } else { KAtlasTextureArray::unbindTextureArray(); } // draw DGL_CALL(glDrawElements(GL_TRIANGLES, indSize, GL_UNSIGNED_SHORT, (U16 *)0)); // clear list after render _kupdata.clear(); indSize = 0; verSize = 0; } } } } return true; }
bool BootAnimation::movie() { ZipFileRO& zip(mZip); size_t numEntries = zip.getNumEntries(); ZipEntryRO desc = zip.findEntryByName("desc.txt"); FileMap* descMap = zip.createEntryFileMap(desc); ALOGE_IF(!descMap, "descMap is null"); if (!descMap) { return false; } String8 desString((char const*)descMap->getDataPtr(), descMap->getDataLength()); char const* s = desString.string(); Animation animation; // Parse the description file for (;;) { const char* endl = strstr(s, "\n"); if (!endl) break; String8 line(s, endl - s); const char* l = line.string(); int fps, width, height, count, pause; char path[256]; char pathType; if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { //LOGD("> w=%d, h=%d, fps=%d", width, height, fps); animation.width = width; animation.height = height; animation.fps = fps; } else if (sscanf(l, " %c %d %d %s", &pathType, &count, &pause, path) == 4) { //LOGD("> type=%c, count=%d, pause=%d, path=%s", pathType, count, pause, path); Animation::Part part; part.playUntilComplete = pathType == 'c'; part.count = count; part.pause = pause; part.path = path; animation.parts.add(part); } s = ++endl; } // read all the data structures const size_t pcount = animation.parts.size(); for (size_t i=0 ; i<numEntries ; i++) { char name[256]; ZipEntryRO entry = zip.findEntryByIndex(i); if (zip.getEntryFileName(entry, name, 256) == 0) { const String8 entryName(name); const String8 path(entryName.getPathDir()); const String8 leaf(entryName.getPathLeaf()); if (leaf.size() > 0) { for (int j=0 ; j<pcount ; j++) { if (path == animation.parts[j].path) { int method; // supports only stored png files if (zip.getEntryInfo(entry, &method, 0, 0, 0, 0, 0)) { if (method == ZipFileRO::kCompressStored) { FileMap* map = zip.createEntryFileMap(entry); if (map) { Animation::Frame frame; frame.name = leaf; frame.map = map; Animation::Part& part(animation.parts.editItemAt(j)); part.frames.add(frame); } } } } } } } } // clear screen glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(mDisplay, mSurface); glBindTexture(GL_TEXTURE_2D, 0); glEnable(GL_TEXTURE_2D); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); const int xc = (mWidth - animation.width) / 2; const int yc = ((mHeight - animation.height) / 2); nsecs_t lastFrame = systemTime(); nsecs_t frameDuration = s2ns(1) / animation.fps; Region clearReg(Rect(mWidth, mHeight)); clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height)); for (int i=0 ; i<pcount ; i++) { const Animation::Part& part(animation.parts[i]); const size_t fcount = part.frames.size(); glBindTexture(GL_TEXTURE_2D, 0); for (int r=0 ; !part.count || r<part.count ; r++) { // Exit any non playuntil complete parts immediately if(exitPending() && !part.playUntilComplete) break; for (int j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { const Animation::Frame& frame(part.frames[j]); nsecs_t lastFrame = systemTime(); if (r > 0) { glBindTexture(GL_TEXTURE_2D, frame.tid); } else { if (part.count != 1) { glGenTextures(1, &frame.tid); glBindTexture(GL_TEXTURE_2D, frame.tid); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } initTexture( frame.map->getDataPtr(), frame.map->getDataLength()); } if (!clearReg.isEmpty()) { Region::const_iterator head(clearReg.begin()); Region::const_iterator tail(clearReg.end()); glEnable(GL_SCISSOR_TEST); while (head != tail) { const Rect& r(*head++); glScissor(r.left, mHeight - r.bottom, r.width(), r.height()); glClear(GL_COLOR_BUFFER_BIT); } glDisable(GL_SCISSOR_TEST); } glDrawTexiOES(xc, yc, 0, animation.width, animation.height); eglSwapBuffers(mDisplay, mSurface); nsecs_t now = systemTime(); nsecs_t delay = frameDuration - (now - lastFrame); //ALOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay)); lastFrame = now; if (delay > 0) { struct timespec spec; spec.tv_sec = (now + delay) / 1000000000; spec.tv_nsec = (now + delay) % 1000000000; int err; do { err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); } while (err<0 && errno == EINTR); } checkExit(); } usleep(part.pause * ns2us(frameDuration)); // For infinite parts, we've now played them at least once, so perhaps exit if(exitPending() && !part.count) break; } // free the textures for this part if (part.count != 1) { for (int j=0 ; j<fcount ; j++) { const Animation::Frame& frame(part.frames[j]); glDeleteTextures(1, &frame.tid); } } } return false; }
bool GPU_fx_compositor_initialize_passes( GPUFX *fx, const rcti *rect, const rcti *scissor_rect, const GPUFXSettings *fx_settings) { int w = BLI_rcti_size_x(rect), h = BLI_rcti_size_y(rect); char err_out[256]; int num_passes = 0; char fx_flag; fx->effects = 0; if (!GPU_non_power_of_two_support() || !GLEW_EXT_framebuffer_object) return false; if (!fx_settings) { cleanup_fx_gl_data(fx, true); return false; } fx_flag = fx_settings->fx_flag; /* disable effects if no options passed for them */ if (!fx_settings->dof) { fx_flag &= ~GPU_FX_FLAG_DOF; } if (!fx_settings->ssao || fx_settings->ssao->samples < 1) { fx_flag &= ~GPU_FX_FLAG_SSAO; } if (!fx_flag) { cleanup_fx_gl_data(fx, true); return false; } /* scissor is missing when drawing offscreen, in that case, dimensions match exactly. In opposite case * add one to match viewport dimensions */ if (scissor_rect) { w++, h++; } fx->num_passes = 0; /* dof really needs a ping-pong buffer to work */ if (fx_flag & GPU_FX_FLAG_DOF) num_passes++; if (fx_flag & GPU_FX_FLAG_SSAO) num_passes++; if (!fx->gbuffer) { fx->gbuffer = GPU_framebuffer_create(); if (!fx->gbuffer) { return false; } } /* try creating the jitter texture */ if (!fx->jitter_buffer) fx->jitter_buffer = create_jitter_texture(); /* check if color buffers need recreation */ if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) { cleanup_fx_gl_data(fx, false); if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) { printf(".256%s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->depth_buffer = GPU_texture_create_depth(w, h, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } } if (fx_flag & GPU_FX_FLAG_SSAO) { if (fx_settings->ssao->samples != fx->ssao_sample_count_cache || !fx->ssao_spiral_samples_tex) { if (fx_settings->ssao->samples < 1) fx_settings->ssao->samples = 1; fx->ssao_sample_count_cache = fx_settings->ssao->samples; if (fx->ssao_spiral_samples_tex) { GPU_texture_free(fx->ssao_spiral_samples_tex); } fx->ssao_spiral_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples); } } else { if (fx->ssao_spiral_samples_tex) { GPU_texture_free(fx->ssao_spiral_samples_tex); fx->ssao_spiral_samples_tex = NULL; } } /* create textures for dof effect */ if (fx_flag & GPU_FX_FLAG_DOF) { bool dof_high_quality = (fx_settings->dof->high_quality != 0) && GPU_geometry_shader_support() && GPU_instanced_drawing_support(); /* cleanup buffers if quality setting has changed (no need to keep more buffers around than necessary ) */ if (dof_high_quality != fx->dof_high_quality) cleanup_fx_dof_buffers(fx); if (dof_high_quality) { fx->dof_downsampled_w = w / 2; fx->dof_downsampled_h = h / 2; if (!fx->dof_half_downsampled_near || !fx->dof_nearfar_coc || !fx->dof_near_blur || !fx->dof_far_blur || !fx->dof_half_downsampled_far) { if (!(fx->dof_half_downsampled_near = GPU_texture_create_2D( fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->dof_half_downsampled_far = GPU_texture_create_2D( fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_procedural( fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, false, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->dof_near_blur = GPU_texture_create_2D( fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->dof_far_blur = GPU_texture_create_2D( fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } } } else { fx->dof_downsampled_w = w / 4; fx->dof_downsampled_h = h / 4; if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) { if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D( fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D( fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D( fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } } } fx->dof_high_quality = dof_high_quality; } else { /* cleanup unnecessary buffers */ cleanup_fx_dof_buffers(fx); } /* we need to pass data between shader stages, allocate an extra color buffer */ if (num_passes > 1) { if (!fx->color_buffer_sec) { if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) { printf(".256%s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } } } else { if (fx->color_buffer_sec) { GPU_framebuffer_texture_detach(fx->color_buffer_sec); GPU_texture_free(fx->color_buffer_sec); fx->color_buffer_sec = NULL; } } /* bind the buffers */ /* first depth buffer, because system assumes read/write buffers */ if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out)) printf("%.256s\n", err_out); if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out)) printf("%.256s\n", err_out); if (!GPU_framebuffer_check_valid(fx->gbuffer, err_out)) printf("%.256s\n", err_out); GPU_texture_bind_as_framebuffer(fx->color_buffer); /* enable scissor test. It's needed to ensure sculpting works correctly */ if (scissor_rect) { int w_sc = BLI_rcti_size_x(scissor_rect) + 1; int h_sc = BLI_rcti_size_y(scissor_rect) + 1; glPushAttrib(GL_SCISSOR_BIT); glEnable(GL_SCISSOR_TEST); glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin, w_sc, h_sc); fx->restore_stencil = true; } else { fx->restore_stencil = false; } fx->effects = fx_flag; if (fx_settings) fx->settings = *fx_settings; fx->gbuffer_dim[0] = w; fx->gbuffer_dim[1] = h; fx->num_passes = num_passes; return true; }
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // If text or lines are blurry when integrating ImGui in your engine: // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplGLUT_RenderDrawLists(ImDrawData* draw_data) { // We are using the OpenGL fixed pipeline to make the example code simpler to read! // A probable faster way to render would be to collate all vertices from all cmd_lists into a single vertex buffer. // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnable(GL_TEXTURE_2D); //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context // Setup orthographic projection matrix const float width = ImGui::GetIO().DisplaySize.x; const float height = ImGui::GetIO().DisplaySize.y; glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); // Render command lists #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->VtxBuffer.front(); const ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, pos))); glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, uv))); glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, col))); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); glScissor((int)pcmd->ClipRect.x, (int)(height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer); } idx_buffer += pcmd->ElemCount; } } #undef OFFSETOF // Restore modified state glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glBindTexture(GL_TEXTURE_2D, 0); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); }
void GLScissorBox::apply(const IntRect &value) { glScissor(value.x, value.y, value.w, value.h); }
void glPopAttrib() { ERROR_IN_BLOCK(); glstack_t *cur = tack_pop(&state.stack.attrib); if (cur == NULL) { ERROR(GL_STACK_UNDERFLOW); } if (cur->mask & GL_COLOR_BUFFER_BIT) { #ifndef USE_ES2 enable_disable(GL_ALPHA_TEST, cur->alpha_test); glAlphaFunc(cur->alpha_test_func, cur->alpha_test_ref); #endif enable_disable(GL_BLEND, cur->blend); glBlendFunc(cur->blend_src_func, cur->blend_dst_func); enable_disable(GL_DITHER, cur->dither); #ifndef USE_ES2 enable_disable(GL_COLOR_LOGIC_OP, cur->color_logic_op); glLogicOp(cur->logic_op); #endif GLfloat *c; glClearColor(v4(cur->clear_color)); glColorMask(v4(cur->color_mask)); } if (cur->mask & GL_CURRENT_BIT) { glColor4f(v4(cur->color)); #ifndef USE_ES2 glNormal3f(v3(cur->normal)); #endif for (int i = 0; i < MAX_TEX; i++) { glMultiTexCoord2f(GL_TEXTURE0 + i, v2(cur->tex[i])); } } if (cur->mask & GL_DEPTH_BUFFER_BIT) { enable_disable(GL_DEPTH_TEST, cur->depth_test); glDepthFunc(cur->depth_func); glClearDepth(cur->clear_depth); glDepthMask(cur->depth_mask); } if (cur->mask & GL_ENABLE_BIT) { int i; GLint max_clip_planes; glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes); for (i = 0; i < max_clip_planes; i++) { enable_disable(GL_CLIP_PLANE0 + i, *(cur->clip_planes_enabled + i)); } GLint max_lights; glGetIntegerv(GL_MAX_LIGHTS, &max_lights); for (i = 0; i < max_lights; i++) { enable_disable(GL_LIGHT0 + i, *(cur->lights_enabled + i)); } enable_disable(GL_ALPHA_TEST, cur->alpha_test); enable_disable(GL_BLEND, cur->blend); enable_disable(GL_CULL_FACE, cur->cull_face); enable_disable(GL_DEPTH_TEST, cur->depth_test); enable_disable(GL_DITHER, cur->dither); enable_disable(GL_FOG, cur->fog); enable_disable(GL_LIGHTING, cur->lighting); enable_disable(GL_LINE_SMOOTH, cur->line_smooth); enable_disable(GL_LINE_STIPPLE, cur->line_stipple); enable_disable(GL_COLOR_LOGIC_OP, cur->color_logic_op); enable_disable(GL_MULTISAMPLE, cur->multisample); enable_disable(GL_NORMALIZE, cur->normalize); enable_disable(GL_POINT_SMOOTH, cur->point_smooth); enable_disable(GL_POLYGON_OFFSET_FILL, cur->polygon_offset_fill); enable_disable(GL_SAMPLE_ALPHA_TO_COVERAGE, cur->sample_alpha_to_coverage); enable_disable(GL_SAMPLE_ALPHA_TO_ONE, cur->sample_alpha_to_one); enable_disable(GL_SAMPLE_COVERAGE, cur->sample_coverage); enable_disable(GL_SCISSOR_TEST, cur->scissor_test); enable_disable(GL_STENCIL_TEST, cur->stencil_test); enable_disable(GL_TEXTURE_2D, cur->texture_2d); } #ifndef USE_ES2 if (cur->mask & GL_FOG_BIT) { enable_disable(GL_FOG, cur->fog); glFogfv(GL_FOG_COLOR, cur->fog_color); glFogf(GL_FOG_DENSITY, cur->fog_density); glFogf(GL_FOG_START, cur->fog_start); glFogf(GL_FOG_END, cur->fog_end); glFogf(GL_FOG_MODE, cur->fog_mode); } #endif if (cur->mask & GL_HINT_BIT) { enable_disable(GL_PERSPECTIVE_CORRECTION_HINT, cur->perspective_hint); enable_disable(GL_POINT_SMOOTH_HINT, cur->point_smooth_hint); enable_disable(GL_LINE_SMOOTH_HINT, cur->line_smooth_hint); enable_disable(GL_FOG_HINT, cur->fog_hint); enable_disable(GL_GENERATE_MIPMAP_HINT, cur->mipmap_hint); } if (cur->mask & GL_LINE_BIT) { enable_disable(GL_LINE_SMOOTH, cur->line_smooth); // TODO: stipple stuff here glLineWidth(cur->line_width); } if (cur->mask & GL_MULTISAMPLE_BIT) { enable_disable(GL_MULTISAMPLE, cur->multisample); enable_disable(GL_SAMPLE_ALPHA_TO_COVERAGE, cur->sample_alpha_to_coverage); enable_disable(GL_SAMPLE_ALPHA_TO_ONE, cur->sample_alpha_to_one); enable_disable(GL_SAMPLE_COVERAGE, cur->sample_coverage); } #ifndef USE_ES2 if (cur->mask & GL_POINT_BIT) { enable_disable(GL_POINT_SMOOTH, cur->point_smooth); glPointSize(cur->point_size); } #endif if (cur->mask & GL_SCISSOR_BIT) { enable_disable(GL_SCISSOR_TEST, cur->scissor_test); glScissor(v4(cur->scissor_box)); } if (cur->mask & GL_TEXTURE_BIT) { glBindTexture(GL_TEXTURE_2D, cur->texture); } free(cur->clip_planes_enabled); free(cur->clip_planes); free(cur->lights_enabled); free(cur->lights); free(cur); }
void DrawParabolicMapWithCube() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-width, width, -height, height, -100000, 100000); gluLookAt(0, 0, 1, 0, 0, 0, 0, -1, 0); glViewport(0, 0, width * 2, height * 2); glScissor(0, 0, width * 2, height * 2); glClearColor(1,1,1, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); double showMapPoints[LOD+1][LOD+1][2]; double showMapTexCoords[LOD+1][LOD+1][2]; for (int i = 0; i <= LOD; i++) { float x = i * 1.0 / LOD; for (int j = 0; j <= LOD; j++) { float y = j * 1.0 / LOD; showMapPoints[i][j][0] = x * width; showMapPoints[i][j][1] = y * height; float parabolic_x, parabolic_y, parabolic_z; // float parabolic_x = ((mapped.x / (2 * (1 + mapped.z))) + 0.5) / 2; // float parabolic_y = (-mapped.y / (2 * (1 + mapped.z))) + 0.5; // float parabolic_z = (1 - parabolic_x * parabolic_x + parabolic_y * parabolic_y) / 2; if (i < LOD / 2) { parabolic_x = (2 * x - 0.5) * 2; parabolic_y = -(2 * y - 1); parabolic_z = (1 - (parabolic_x * parabolic_x + parabolic_y * parabolic_y)) / 2; } else { parabolic_x = (2 * (x - 0.5) - 0.5) * 2; parabolic_y = -(2 * y - 1); parabolic_z = -(1 - (parabolic_x * parabolic_x + parabolic_y * parabolic_y)) / 2; } // printf("para : %f, %f, %f\n",parabolic_x, parabolic_y, parabolic_z); Vector3d mapped = Vector3d(parabolic_x, parabolic_y, parabolic_z); mapped.normalize(); float padding_y = 1/3.0; float padding_x = 1/4.0; if (mapped.x >= std::abs(mapped.y) && mapped.x >= std::abs(mapped.z)) { // right showMapTexCoords[i][j][0] = (-mapped.z / mapped.x + 1) / 2 / 4 + padding_x * 2; showMapTexCoords[i][j][1] = (-mapped.y / mapped.x + 1) / 2 / 3 + padding_y; } else if (mapped.y >= std::abs(mapped.x) && mapped.y >= std::abs(mapped.z)) { // top showMapTexCoords[i][j][0] = (mapped.x / mapped.y + 1) / 2 / 4 + padding_x; showMapTexCoords[i][j][1] = (mapped.z / mapped.y + 1) / 2 / 3; } else if (mapped.z >= std::abs(mapped.x) && mapped.z >= std::abs(mapped.y)) { // front showMapTexCoords[i][j][0] = (mapped.x / mapped.z + 1) / 2 / 4 + padding_x; showMapTexCoords[i][j][1] = (-mapped.y / mapped.z + 1) / 2 / 3 + padding_y; } else if (mapped.x <= -std::abs(mapped.y) && mapped.x <= -std::abs(mapped.z)) { // left showMapTexCoords[i][j][0] = (-mapped.z / mapped.x + 1) / 2 / 4; showMapTexCoords[i][j][1] = (mapped.y / mapped.x + 1) / 2 / 3 + padding_y; } else if (mapped.y <= -std::abs(mapped.x) && mapped.y <= -std::abs(mapped.z)) { // bottom showMapTexCoords[i][j][0] = (-mapped.x / mapped.y + 1) / 2 / 4 + padding_x; showMapTexCoords[i][j][1] = (mapped.z / mapped.y + 1) / 2 / 3 + padding_y * 2; } else if (mapped.z <= -std::abs(mapped.x) && mapped.z <= -std::abs(mapped.y)) { // back showMapTexCoords[i][j][0] = (mapped.x / mapped.z + 1) / 2 / 4 + padding_x * 3; showMapTexCoords[i][j][1] = (mapped.y / mapped.z + 1) / 2 / 3 + padding_y; } // showMapTexCoords[i][j][0] = x; // showMapTexCoords[i][j][1] = y; } } glEnable(GL_TEXTURE_2D); for (int i = 0; i < LOD; i++) { glBegin(GL_QUAD_STRIP); for (int j = 0; j < LOD; j++) { glTexCoord2dv(showMapTexCoords[i][j]); glVertex2dv(showMapPoints[i][j]); glTexCoord2dv(showMapTexCoords[i + 1][j]); glVertex2dv(showMapPoints[i + 1][j]); } glEnd(); } glDisable(GL_TEXTURE_2D); return; }
void DrawParabolicMapWithSphere() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-width, width, -height, height, -100000, 100000); gluLookAt(0, 0, 1, 0, 0, 0, 0, -1, 0); glViewport(0, 0, width * 2, height * 2); glScissor(0, 0, width * 2, height * 2); glClearColor(1,1,1, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); double showMapPoints[LOD+1][LOD+1][2]; double showMapTexCoords[LOD+1][LOD+1][2]; for (int i = 0; i <= LOD; i++) { float x = i * 1.0 / LOD; for (int j = 0; j <= LOD; j++) { float y = j * 1.0 / LOD; showMapPoints[i][j][0] = x * width; showMapPoints[i][j][1] = y * height; float parabolic_x, parabolic_y, parabolic_z; // float parabolic_x = ((mapped.x / (2 * (1 + mapped.z))) + 0.5) / 2; // float parabolic_y = (-mapped.y / (2 * (1 + mapped.z))) + 0.5; // float parabolic_z = (1 - parabolic_x * parabolic_x + parabolic_y * parabolic_y) / 2; if (i < LOD / 2) { parabolic_x = (2 * x - 0.5) * 2; parabolic_y = -(2 * y - 1); parabolic_z = (1 - (parabolic_x * parabolic_x + parabolic_y * parabolic_y)) / 2; } else { parabolic_x = (2 * (x - 0.5) - 0.5) * 2; parabolic_y = -(2 * y - 1); parabolic_z = -(1 - (parabolic_x * parabolic_x + parabolic_y * parabolic_y)) / 2; } // printf("para : %f, %f, %f\n",parabolic_x, parabolic_y, parabolic_z); Vector3d mapped = Vector3d(parabolic_x, parabolic_y, parabolic_z); mapped.normalize(); double sum = sqrt(mapped.x*mapped.x + mapped.y*mapped.y + pow(mapped.z+1,2)); showMapTexCoords[i][j][0] = (mapped.x/sum + 1) / 2; showMapTexCoords[i][j][1] = (-mapped.y/sum + 1) / 2; // showMapTexCoords[i][j][0] = x; // showMapTexCoords[i][j][1] = y; } } glEnable(GL_TEXTURE_2D); for (int i = 0; i < LOD; i++) { glBegin(GL_QUAD_STRIP); for (int j = 0; j < LOD; j++) { glTexCoord2dv(showMapTexCoords[i][j]); glVertex2dv(showMapPoints[i][j]); glTexCoord2dv(showMapTexCoords[i + 1][j]); glVertex2dv(showMapPoints[i + 1][j]); } glEnd(); } glDisable(GL_TEXTURE_2D); return; }
/* CTextureCanvas::drawTexture * Draws the currently opened composite texture *******************************************************************/ void CTextureCanvas::drawTexture() { // Push matrix glPushMatrix(); // Translate to middle of the canvas glTranslated(GetSize().x * 0.5, GetSize().y * 0.5, 0); // Zoom double yscale = (tx_arc ? scale * 1.2 : scale); glScaled(scale, yscale, 1); // Draw offset guides if needed drawOffsetLines(); // Apply texture scale double tscalex = 1; double tscaley = 1; if (tex_scale) { tscalex = texture->getScaleX(); if (tscalex == 0) tscalex = 1; tscaley = texture->getScaleY(); if (tscaley == 0) tscaley = 1; glScaled(1.0 / tscalex, 1.0 / tscaley, 1); } // Calculate top-left position of texture (for glScissor, since it ignores the current translation/scale) point2_t screen_tl = texToScreenPosition(0, 0); int left = screen_tl.x; int top = screen_tl.y; // Translate by offsets if needed if (view_type == 0) // No offsets glTranslated(texture->getWidth() * -0.5, texture->getHeight() * -0.5, 0); if (view_type >= 1) // Sprite offsets glTranslated(-texture->getOffsetX(), -texture->getOffsetY(), 0); if (view_type == 2) // HUD offsets glTranslated(-160 * tscalex, -100 * tscaley, 0); // Draw the texture border drawTextureBorder(); // Enable textures glEnable(GL_TEXTURE_2D); // First, draw patches semitransparently (for anything outside the texture) // But only if we are drawing stuff outside the texture area if (draw_outside) { for (uint32_t a = 0; a < texture->nPatches(); a++) drawPatch(a, true); } // Reset colouring OpenGL::setColour(COL_WHITE); // If we're currently dragging, draw a 'basic' preview of the texture using opengl if (dragging) { glEnable(GL_SCISSOR_TEST); glScissor(left, top, texture->getWidth() * scale * (1.0 / tscalex), texture->getHeight() * yscale * (1.0 / tscaley)); for (uint32_t a = 0; a < texture->nPatches(); a++) drawPatch(a); glDisable(GL_SCISSOR_TEST); } // Otherwise, draw the fully generated texture else { // Generate if needed if (!tex_preview.isLoaded()) { // Determine image type SIType type = PALMASK; if (blend_rgba) type = RGBA; // CTexture -> temp Image -> GLTexture SImage temp(type); texture->toImage(temp, parent, &palette, blend_rgba); tex_preview.loadImage(&temp, &palette); } // Draw it tex_preview.draw2d(); } // Disable textures glDisable(GL_TEXTURE_2D); // Now loop through selected patches and draw selection outlines OpenGL::setColour(70, 210, 220, 255, BLEND_NORMAL); glEnable(GL_LINE_SMOOTH); glLineWidth(1.5f); for (size_t a = 0; a < selected_patches.size(); a++) { // Skip if not selected if (!selected_patches[a]) continue; // Get patch CTPatch* patch = texture->getPatch(a); CTPatchEx* epatch = (CTPatchEx*)patch; // Check for rotation if (texture->isExtended() && (epatch->getRotation() == 90 || epatch->getRotation() == -90)) { // Draw outline, width/height swapped glBegin(GL_LINE_LOOP); glVertex2i(patch->xOffset(), patch->yOffset()); glVertex2i(patch->xOffset(), patch->yOffset() + (int)patch_textures[a]->getWidth()); glVertex2i(patch->xOffset() + (int)patch_textures[a]->getHeight(), patch->yOffset() + (int)patch_textures[a]->getWidth()); glVertex2i(patch->xOffset() + (int)patch_textures[a]->getHeight(), patch->yOffset()); glEnd(); } else { // Draw outline glBegin(GL_LINE_LOOP); glVertex2i(patch->xOffset(), patch->yOffset()); glVertex2i(patch->xOffset(), patch->yOffset() + (int)patch_textures[a]->getHeight()); glVertex2i(patch->xOffset() + (int)patch_textures[a]->getWidth(), patch->yOffset() + (int)patch_textures[a]->getHeight()); glVertex2i(patch->xOffset() + (int)patch_textures[a]->getWidth(), patch->yOffset()); glEnd(); } } // Finally, draw a hilight outline if anything is hilighted if (hilight_patch >= 0 && hilight_patch < (int)texture->nPatches()) { // Set colour OpenGL::setColour(255, 255, 255, 150, BLEND_ADDITIVE); // Get patch CTPatch* patch = texture->getPatch(hilight_patch); CTPatchEx* epatch = (CTPatchEx*)patch; GLTexture* patch_texture = patch_textures[hilight_patch]; // Check for rotation if (texture->isExtended() && (epatch->getRotation() == 90 || epatch->getRotation() == -90)) { // Draw outline, width/height swapped glBegin(GL_LINE_LOOP); glVertex2i(patch->xOffset(), patch->yOffset()); glVertex2i(patch->xOffset(), patch->yOffset() + (int)patch_texture->getWidth()); glVertex2i(patch->xOffset() + (int)patch_texture->getHeight(), patch->yOffset() + (int)patch_texture->getWidth()); glVertex2i(patch->xOffset() + (int)patch_texture->getHeight(), patch->yOffset()); glEnd(); } else { // Draw outline glBegin(GL_LINE_LOOP); glVertex2i(patch->xOffset(), patch->yOffset()); glVertex2i(patch->xOffset(), patch->yOffset() + (int)patch_texture->getHeight()); glVertex2i(patch->xOffset() + (int)patch_texture->getWidth(), patch->yOffset() + (int)patch_texture->getHeight()); glVertex2i(patch->xOffset() + (int)patch_texture->getWidth(), patch->yOffset()); glEnd(); } } glDisable(GL_LINE_SMOOTH); glLineWidth(1.0f); // Pop matrix glPopMatrix(); }
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples) { m_xfbFramebuffer = 0; m_efbColor = 0; m_efbDepth = 0; m_efbColorSwap = 0; m_resolvedColorTexture = 0; m_resolvedDepthTexture = 0; m_targetWidth = targetWidth; m_targetHeight = targetHeight; m_msaaSamples = msaaSamples; // The EFB can be set to different pixel formats by the game through the // BPMEM_ZCOMPARE register (which should probably have a different name). // They are: // - 24-bit RGB (8-bit components) with 24-bit Z // - 24-bit RGBA (6-bit components) with 24-bit Z // - Multisampled 16-bit RGB (5-6-5 format) with 16-bit Z // We only use one EFB format here: 32-bit ARGB with 24-bit Z. // Multisampling depends on user settings. // The distinction becomes important for certain operations, i.e. the // alpha channel should be ignored if the EFB does not have one. glActiveTexture(GL_TEXTURE9); GLuint glObj[3]; glGenTextures(3, glObj); m_efbColor = glObj[0]; m_efbDepth = glObj[1]; m_efbColorSwap = glObj[2]; m_EFBLayers = (g_ActiveConfig.iStereoMode > 0) ? 2 : 1; m_efbFramebuffer.resize(m_EFBLayers); m_resolvedFramebuffer.resize(m_EFBLayers); // OpenGL MSAA textures are a different kind of texture type and must be allocated // with a different function, so we create them separately. if (m_msaaSamples <= 1) { m_textureType = GL_TEXTURE_2D_ARRAY; glBindTexture(m_textureType, m_efbColor); glTexParameteri(m_textureType, GL_TEXTURE_MAX_LEVEL, 0); glTexImage3D(m_textureType, 0, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(m_textureType, m_efbDepth); glTexParameteri(m_textureType, GL_TEXTURE_MAX_LEVEL, 0); glTexImage3D(m_textureType, 0, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); glBindTexture(m_textureType, m_efbColorSwap); glTexParameteri(m_textureType, GL_TEXTURE_MAX_LEVEL, 0); glTexImage3D(m_textureType, 0, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); } else { GLenum resolvedType = GL_TEXTURE_2D_ARRAY; // Only use a layered multisample texture if needed. Some drivers // slow down significantly with single-layered multisample textures. if (m_EFBLayers > 1) { m_textureType = GL_TEXTURE_2D_MULTISAMPLE_ARRAY; if (g_ogl_config.bSupports3DTextureStorage) { glBindTexture(m_textureType, m_efbColor); glTexStorage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, m_efbDepth); glTexStorage3DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, m_efbColorSwap); glTexStorage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, 0); } else { glBindTexture(m_textureType, m_efbColor); glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, m_efbDepth); glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, m_efbColorSwap); glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, 0); } } else { m_textureType = GL_TEXTURE_2D_MULTISAMPLE; if (g_ogl_config.bSupports2DTextureStorage) { glBindTexture(m_textureType, m_efbColor); glTexStorage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight, false); glBindTexture(m_textureType, m_efbDepth); glTexStorage2DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, false); glBindTexture(m_textureType, m_efbColorSwap); glTexStorage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight, false); glBindTexture(m_textureType, 0); } else { glBindTexture(m_textureType, m_efbColor); glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, false); glBindTexture(m_textureType, m_efbDepth); glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, false); glBindTexture(m_textureType, m_efbColorSwap); glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, false); glBindTexture(m_textureType, 0); } } // Although we are able to access the multisampled texture directly, we don't do it everywhere. // The old way is to "resolve" this multisampled texture by copying it into a non-sampled texture. // This would lead to an unneeded copy of the EFB, so we are going to avoid it. // But as this job isn't done right now, we do need that texture for resolving: glGenTextures(2, glObj); m_resolvedColorTexture = glObj[0]; m_resolvedDepthTexture = glObj[1]; glBindTexture(resolvedType, m_resolvedColorTexture); glTexParameteri(resolvedType, GL_TEXTURE_MAX_LEVEL, 0); glTexImage3D(resolvedType, 0, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(resolvedType, m_resolvedDepthTexture); glTexParameteri(resolvedType, GL_TEXTURE_MAX_LEVEL, 0); glTexImage3D(resolvedType, 0, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); // Bind resolved textures to resolved framebuffer. glGenFramebuffers(m_EFBLayers, m_resolvedFramebuffer.data()); glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer[0]); FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolvedType, m_resolvedColorTexture, 0); FramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, resolvedType, m_resolvedDepthTexture, 0); // Bind all the other layers as separate FBOs for blitting. for (unsigned int i = 1; i < m_EFBLayers; i++) { glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer[i]); glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_resolvedColorTexture, 0, i); glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_resolvedDepthTexture, 0, i); } } // Create XFB framebuffer; targets will be created elsewhere. glGenFramebuffers(1, &m_xfbFramebuffer); // Bind target textures to EFB framebuffer. glGenFramebuffers(m_EFBLayers, m_efbFramebuffer.data()); glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[0]); FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_textureType, m_efbColor, 0); FramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_textureType, m_efbDepth, 0); // Bind all the other layers as separate FBOs for blitting. for (unsigned int i = 1; i < m_EFBLayers; i++) { glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[i]); glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_efbColor, 0, i); glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_efbDepth, 0, i); } // EFB framebuffer is currently bound, make sure to clear its alpha value to 1.f glViewport(0, 0, m_targetWidth, m_targetHeight); glScissor(0, 0, m_targetWidth, m_targetHeight); glClearColor(0.f, 0.f, 0.f, 1.f); glClearDepthf(1.0f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // reinterpret pixel format const char* vs = m_EFBLayers > 1 ? "void main(void) {\n" " vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n" " gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n" "}\n" : "flat out int layer;\n" "void main(void) {\n" " layer = 0;\n" " vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n" " gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n" "}\n"; // The way to sample the EFB is based on the on the current configuration. // As we use the same sampling way for both interpreting shaders, the sampling // shader are generated first: std::string sampler; if (m_msaaSamples <= 1) { // non-msaa, so just fetch the pixel sampler = "SAMPLER_BINDING(9) uniform sampler2DArray samp9;\n" "vec4 sampleEFB(ivec3 pos) {\n" " return texelFetch(samp9, pos, 0);\n" "}\n"; } else if (g_ActiveConfig.backend_info.bSupportsSSAA) { // msaa + sample shading available, so just fetch the sample // This will lead to sample shading, but it's the only way to not loose // the values of each sample. if (m_EFBLayers > 1) { sampler = "SAMPLER_BINDING(9) uniform sampler2DMSArray samp9;\n" "vec4 sampleEFB(ivec3 pos) {\n" " return texelFetch(samp9, pos, gl_SampleID);\n" "}\n"; } else { sampler = "SAMPLER_BINDING(9) uniform sampler2DMS samp9;\n" "vec4 sampleEFB(ivec3 pos) {\n" " return texelFetch(samp9, pos.xy, gl_SampleID);\n" "}\n"; } } else { // msaa without sample shading: calculate the mean value of the pixel std::stringstream samples; samples << m_msaaSamples; if (m_EFBLayers > 1) { sampler = "SAMPLER_BINDING(9) uniform sampler2DMSArray samp9;\n" "vec4 sampleEFB(ivec3 pos) {\n" " vec4 color = vec4(0.0, 0.0, 0.0, 0.0);\n" " for(int i=0; i<" + samples.str() + "; i++)\n" " color += texelFetch(samp9, pos, 0), i);\n" " return color / " + samples.str() + ";\n" "}\n"; } else { sampler = "SAMPLER_BINDING(9) uniform sampler2DMS samp9;\n" "vec4 sampleEFB(ivec3 pos) {\n" " vec4 color = vec4(0.0, 0.0, 0.0, 0.0);\n" " for(int i=0; i<" + samples.str() + "; i++)\n" " color += texelFetch(samp9, pos.xy, i);\n" " return color / " + samples.str() + ";\n" "}\n"; } } std::string ps_rgba6_to_rgb8 = sampler + "flat in int layer;\n" "out vec4 ocol0;\n" "void main()\n" "{\n" " ivec4 src6 = ivec4(round(sampleEFB(ivec3(gl_FragCoord.xy, layer)) * 63.f));\n" " ivec4 dst8;\n" " dst8.r = (src6.r << 2) | (src6.g >> 4);\n" " dst8.g = ((src6.g & 0xF) << 4) | (src6.b >> 2);\n" " dst8.b = ((src6.b & 0x3) << 6) | src6.a;\n" " dst8.a = 255;\n" " ocol0 = float4(dst8) / 255.f;\n" "}"; std::string ps_rgb8_to_rgba6 = sampler + "flat in int layer;\n" "out vec4 ocol0;\n" "void main()\n" "{\n" " ivec4 src8 = ivec4(round(sampleEFB(ivec3(gl_FragCoord.xy, layer)) * 255.f));\n" " ivec4 dst6;\n" " dst6.r = src8.r >> 2;\n" " dst6.g = ((src8.r & 0x3) << 4) | (src8.g >> 4);\n" " dst6.b = ((src8.g & 0xF) << 2) | (src8.b >> 6);\n" " dst6.a = src8.b & 0x3F;\n" " ocol0 = float4(dst6) / 63.f;\n" "}"; std::stringstream vertices, layers; vertices << m_EFBLayers * 3; layers << m_EFBLayers; std::string gs = "layout(triangles) in;\n" "layout(triangle_strip, max_vertices = " + vertices.str() + ") out;\n" "flat out int layer;\n" "void main()\n" "{\n" " for (int j = 0; j < " + layers.str() + "; ++j) {\n" " for (int i = 0; i < 3; ++i) {\n" " layer = j;\n" " gl_Layer = j;\n" " gl_Position = gl_in[i].gl_Position;\n" " EmitVertex();\n" " }\n" " EndPrimitive();\n" " }\n" "}\n"; ProgramShaderCache::CompileShader(m_pixel_format_shaders[0], vs, ps_rgb8_to_rgba6.c_str(), (m_EFBLayers > 1) ? gs : ""); ProgramShaderCache::CompileShader(m_pixel_format_shaders[1], vs, ps_rgba6_to_rgb8.c_str(), (m_EFBLayers > 1) ? gs : ""); ProgramShaderCache::CompileShader(m_EfbPokes, StringFromFormat( "in vec2 rawpos;\n" "in vec4 color0;\n" // color "in int color1;\n" // depth "out vec4 v_c;\n" "out float v_z;\n" "void main(void) {\n" " gl_Position = vec4(((rawpos + 0.5) / vec2(640.0, 528.0) * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0);\n" " gl_PointSize = %d.0 / 640.0;\n" " v_c = color0.bgra;\n" " v_z = float(color1 & 0xFFFFFF) / 16777216.0;\n" "}\n", m_targetWidth), StringFromFormat( "in vec4 %s_c;\n" "in float %s_z;\n" "out vec4 ocol0;\n" "void main(void) {\n" " ocol0 = %s_c;\n" " gl_FragDepth = %s_z;\n" "}\n", m_EFBLayers > 1 ? "g" : "v", m_EFBLayers > 1 ? "g" : "v", m_EFBLayers > 1 ? "g" : "v", m_EFBLayers > 1 ? "g" : "v"), m_EFBLayers > 1 ? StringFromFormat( "layout(points) in;\n" "layout(points, max_vertices = %d) out;\n" "in vec4 v_c[1];\n" "in float v_z[1];\n" "out vec4 g_c;\n" "out float g_z;\n" "void main()\n" "{\n" " for (int j = 0; j < %d; ++j) {\n" " gl_Layer = j;\n" " gl_Position = gl_in[0].gl_Position;\n" " gl_PointSize = %d.0 / 640.0;\n" " g_c = v_c[0];\n" " g_z = v_z[0];\n" " EmitVertex();\n" " EndPrimitive();\n" " }\n" "}\n", m_EFBLayers, m_EFBLayers, m_targetWidth) : ""); glGenBuffers(1, &m_EfbPokes_VBO); glGenVertexArrays(1, &m_EfbPokes_VAO); glBindBuffer(GL_ARRAY_BUFFER, m_EfbPokes_VBO); glBindVertexArray(m_EfbPokes_VAO ); glEnableVertexAttribArray(SHADER_POSITION_ATTRIB); glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_UNSIGNED_SHORT, 0, sizeof(EfbPokeData), (void*)offsetof(EfbPokeData, x)); glEnableVertexAttribArray(SHADER_COLOR0_ATTRIB); glVertexAttribPointer(SHADER_COLOR0_ATTRIB, 4, GL_UNSIGNED_BYTE, 1, sizeof(EfbPokeData), (void*)offsetof(EfbPokeData, data)); glEnableVertexAttribArray(SHADER_COLOR1_ATTRIB); glVertexAttribIPointer(SHADER_COLOR1_ATTRIB, 1, GL_INT, sizeof(EfbPokeData), (void*)offsetof(EfbPokeData, data)); if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL) glEnable(GL_PROGRAM_POINT_SIZE); }
RenderTexture::RenderTexture(int width, int height, int sample_count, int jcolor_format, int jdepth_format, bool resolve_depth, int* texture_parameters) : Texture(new GLTexture(TARGET, texture_parameters)), width_(width), height_( height), sample_count_(sample_count), renderTexture_gl_frame_buffer_(new GLFrameBuffer()) { initialize(width, height); GLenum depth_format; glBindTexture(TARGET, gl_texture_->id()); switch (jcolor_format) { case ColorFormat::COLOR_565: glTexImage2D(TARGET, 0, GL_RGB, width_, height_, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0); break; case ColorFormat::COLOR_5551: glTexImage2D(TARGET, 0, GL_RGB5_A1, width_, height_, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 0); break; case ColorFormat::COLOR_4444: glTexImage2D(TARGET, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 0); break; case ColorFormat::COLOR_8888: glTexImage2D(TARGET, 0, GL_RGBA8, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); break; case ColorFormat::COLOR_8888_sRGB: glTexImage2D(TARGET, 0, GL_SRGB8_ALPHA8, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); break; default: break; } switch (jdepth_format) { case DepthFormat::DEPTH_24: depth_format = GL_DEPTH_COMPONENT24_OES; break; case DepthFormat::DEPTH_24_STENCIL_8: depth_format = GL_DEPTH24_STENCIL8_OES; break; default: depth_format = GL_DEPTH_COMPONENT16; break; } if (sample_count <= 1) { generateRenderTextureNoMultiSampling(jdepth_format, depth_format, width, height); } else if (resolve_depth) { generateRenderTexture(sample_count, jdepth_format, depth_format, width, height, jcolor_format); } else { generateRenderTextureEXT(sample_count, jdepth_format, depth_format, width, height); } if (jdepth_format != DepthFormat::DEPTH_0) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderTexture_gl_render_buffer_->id()); } glScissor(0, 0, width, height); glViewport(0, 0, width, height); glClearColor(0, 1, 0, 1); glClear(GL_COLOR_BUFFER_BIT); if (resolve_depth && sample_count > 1) { delete renderTexture_gl_resolve_buffer_; renderTexture_gl_resolve_buffer_ = new GLFrameBuffer(); glBindFramebuffer(GL_FRAMEBUFFER, renderTexture_gl_resolve_buffer_->id()); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl_texture_->id(), 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { LOGE( "resolve FBO %i is not complete: 0x%x", renderTexture_gl_resolve_buffer_->id(), status); } } glBindFramebuffer(GL_FRAMEBUFFER, 0); }
void imguiRenderGLDraw() { const imguiGfxCmd* q = imguiGetRenderQueue(); int nq = imguiGetRenderQueueSize(); const float s = 1.0f/8.0f; glDisable(GL_SCISSOR_TEST); for (int i = 0; i < nq; ++i) { const imguiGfxCmd& cmd = q[i]; if (cmd.type == IMGUI_GFXCMD_RECT) { if (cmd.rect.r == 0) { drawRect((float)cmd.rect.x*s+0.5f, (float)cmd.rect.y*s+0.5f, (float)cmd.rect.w*s-1, (float)cmd.rect.h*s-1, 1.0f, cmd.col); } else { drawRoundedRect((float)cmd.rect.x*s+0.5f, (float)cmd.rect.y*s+0.5f, (float)cmd.rect.w*s-1, (float)cmd.rect.h*s-1, (float)cmd.rect.r*s, 1.0f, cmd.col); } } else if (cmd.type == IMGUI_GFXCMD_LINE) { drawLine(cmd.line.x0*s, cmd.line.y0*s, cmd.line.x1*s, cmd.line.y1*s, cmd.line.r*s, 1.0f, cmd.col); } else if (cmd.type == IMGUI_GFXCMD_TRIANGLE) { if (cmd.flags == 1) { const float verts[3*2] = { (float)cmd.rect.x*s+0.5f, (float)cmd.rect.y*s+0.5f, (float)cmd.rect.x*s+0.5f+(float)cmd.rect.w*s-1, (float)cmd.rect.y*s+0.5f+(float)cmd.rect.h*s/2-0.5f, (float)cmd.rect.x*s+0.5f, (float)cmd.rect.y*s+0.5f+(float)cmd.rect.h*s-1, }; drawPolygon(verts, 3, 1.0f, cmd.col); } if (cmd.flags == 2) { const float verts[3*2] = { (float)cmd.rect.x*s+0.5f, (float)cmd.rect.y*s+0.5f+(float)cmd.rect.h*s-1, (float)cmd.rect.x*s+0.5f+(float)cmd.rect.w*s/2-0.5f, (float)cmd.rect.y*s+0.5f, (float)cmd.rect.x*s+0.5f+(float)cmd.rect.w*s-1, (float)cmd.rect.y*s+0.5f+(float)cmd.rect.h*s-1, }; drawPolygon(verts, 3, 1.0f, cmd.col); } } else if (cmd.type == IMGUI_GFXCMD_TEXT) { drawText(cmd.text.x, cmd.text.y, cmd.text.text, cmd.text.align, cmd.col); } else if (cmd.type == IMGUI_GFXCMD_SCISSOR) { if (cmd.flags) { glEnable(GL_SCISSOR_TEST); glScissor(cmd.rect.x, cmd.rect.y, cmd.rect.w, cmd.rect.h); } else { glDisable(GL_SCISSOR_TEST); } } } glDisable(GL_SCISSOR_TEST); }
void GLGSRender::ExecCMD() { //return; if(!LoadProgram()) { ConLog.Error("LoadProgram failed."); Emu.Pause(); return; } if(!m_fbo.IsCreated() || RSXThread::m_width != last_width || RSXThread::m_height != last_height || last_depth_format != m_surface_depth_format) { ConLog.Warning("New FBO (%dx%d)", RSXThread::m_width, RSXThread::m_height); last_width = RSXThread::m_width; last_height = RSXThread::m_height; last_depth_format = m_surface_depth_format; m_fbo.Create(); checkForGlError("m_fbo.Create"); m_fbo.Bind(); m_rbo.Create(4 + 1); checkForGlError("m_rbo.Create"); for(int i=0; i<4; ++i) { m_rbo.Bind(i); m_rbo.Storage(GL_RGBA, RSXThread::m_width, RSXThread::m_height); checkForGlError("m_rbo.Storage(GL_RGBA)"); } m_rbo.Bind(4); switch(m_surface_depth_format) { case 1: m_rbo.Storage(GL_DEPTH_COMPONENT16, RSXThread::m_width, RSXThread::m_height); checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT16)"); break; case 2: m_rbo.Storage(GL_DEPTH24_STENCIL8, RSXThread::m_width, RSXThread::m_height); checkForGlError("m_rbo.Storage(GL_DEPTH24_STENCIL8)"); break; default: ConLog.Error("Bad depth format! (%d)", m_surface_depth_format); assert(0); break; } for(int i=0; i<4; ++i) { m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0 + i, m_rbo.GetId(i)); checkForGlError(wxString::Format("m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT%d)", i)); } m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT, m_rbo.GetId(4)); checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT)"); if(m_surface_depth_format == 2) { m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT, m_rbo.GetId(4)); checkForGlError("m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT)"); } } if(!m_set_surface_clip_horizontal) { m_surface_clip_x = 0; m_surface_clip_w = RSXThread::m_width; } if(!m_set_surface_clip_vertical) { m_surface_clip_y = 0; m_surface_clip_h = RSXThread::m_height; } m_fbo.Bind(); if(Ini.GSDumpDepthBuffer.GetValue()) WriteDepthBuffer(); static const GLenum draw_buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; switch(m_surface_colour_target) { case 0x0: break; case 0x1: glDrawBuffer(draw_buffers[0]); break; case 0x2: glDrawBuffer(draw_buffers[1]); break; case 0x13: glDrawBuffers(2, draw_buffers); break; case 0x17: glDrawBuffers(3, draw_buffers); break; case 0x1f: glDrawBuffers(4, draw_buffers); break; default: ConLog.Error("Bad surface colour target: %d", m_surface_colour_target); break; } if(m_set_color_mask) { glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a); checkForGlError("glColorMask"); } if(m_set_viewport_horizontal && m_set_viewport_vertical) { glViewport(m_viewport_x, RSXThread::m_height-m_viewport_y-m_viewport_h, m_viewport_w, m_viewport_h); checkForGlError("glViewport"); } if(m_set_scissor_horizontal && m_set_scissor_vertical) { glScissor(m_scissor_x, RSXThread::m_height-m_scissor_y-m_scissor_h, m_scissor_w, m_scissor_h); checkForGlError("glScissor"); } if(m_clear_surface_mask) { GLbitfield f = 0; if (m_clear_surface_mask & 0x1) { glClearDepth(m_clear_surface_z / (float)0xffffff); f |= GL_DEPTH_BUFFER_BIT; } if (m_clear_surface_mask & 0x2) { glClearStencil(m_clear_surface_s); f |= GL_STENCIL_BUFFER_BIT; } if (m_clear_surface_mask & 0xF0) { glClearColor( m_clear_surface_color_r / 255.0f, m_clear_surface_color_g / 255.0f, m_clear_surface_color_b / 255.0f, m_clear_surface_color_a / 255.0f); f |= GL_COLOR_BUFFER_BIT; } glClear(f); } if(m_set_front_polygon_mode) { glPolygonMode(GL_FRONT, m_front_polygon_mode); checkForGlError("glPolygonMode"); } Enable(m_depth_test_enable, GL_DEPTH_TEST); Enable(m_set_alpha_test, GL_ALPHA_TEST); Enable(m_set_depth_bounds_test, GL_DEPTH_BOUNDS_TEST_EXT); Enable(m_set_blend, GL_BLEND); Enable(m_set_logic_op, GL_LOGIC_OP); Enable(m_set_cull_face_enable, GL_CULL_FACE); Enable(m_set_dither, GL_DITHER); Enable(m_set_stencil_test, GL_STENCIL_TEST); Enable(m_set_line_smooth, GL_LINE_SMOOTH); Enable(m_set_poly_smooth, GL_POLYGON_SMOOTH); Enable(m_set_poly_offset_fill, GL_POLYGON_OFFSET_FILL); Enable(m_set_poly_offset_line, GL_POLYGON_OFFSET_LINE); Enable(m_set_poly_offset_point, GL_POLYGON_OFFSET_POINT); //Enable(m_set_restart_index, GL_PRIMITIVE_RESTART); //Requires OpenGL 3.1+ if(m_set_clip_plane) { Enable(m_clip_plane_0, GL_CLIP_PLANE0); Enable(m_clip_plane_1, GL_CLIP_PLANE1); Enable(m_clip_plane_2, GL_CLIP_PLANE2); Enable(m_clip_plane_3, GL_CLIP_PLANE3); Enable(m_clip_plane_4, GL_CLIP_PLANE4); Enable(m_clip_plane_5, GL_CLIP_PLANE5); checkForGlError("m_set_clip_plane"); } checkForGlError("glEnable"); if(m_set_two_sided_stencil_test_enable) { if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) { glStencilOpSeparate(GL_FRONT, m_stencil_fail, m_stencil_zfail, m_stencil_zpass); checkForGlError("glStencilOpSeparate"); } if(m_set_stencil_mask) { glStencilMaskSeparate(GL_FRONT, m_stencil_mask); checkForGlError("glStencilMaskSeparate"); } if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) { glStencilFuncSeparate(GL_FRONT, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); checkForGlError("glStencilFuncSeparate"); } if(m_set_back_stencil_fail && m_set_back_stencil_zfail && m_set_back_stencil_zpass) { glStencilOpSeparate(GL_BACK, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass); checkForGlError("glStencilOpSeparate(GL_BACK)"); } if(m_set_back_stencil_mask) { glStencilMaskSeparate(GL_BACK, m_back_stencil_mask); checkForGlError("glStencilMaskSeparate(GL_BACK)"); } if(m_set_back_stencil_func && m_set_back_stencil_func_ref && m_set_back_stencil_func_mask) { glStencilFuncSeparate(GL_BACK, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask); checkForGlError("glStencilFuncSeparate(GL_BACK)"); } } else { if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) { glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass); checkForGlError("glStencilOp"); } if(m_set_stencil_mask) { glStencilMask(m_stencil_mask); checkForGlError("glStencilMask"); } if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) { glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); checkForGlError("glStencilFunc"); } } if(m_set_shade_mode) { glShadeModel(m_shade_mode); checkForGlError("glShadeModel"); } if(m_set_depth_mask) { glDepthMask(m_depth_mask); checkForGlError("glDepthMask"); } if(m_set_depth_func) { glDepthFunc(m_depth_func); //ConLog.Warning("glDepthFunc(0x%x)", m_depth_func); checkForGlError("glDepthFunc"); } if(m_set_depth_bounds) { //ConLog.Warning("glDepthBounds(%f, %f)", m_depth_bounds_min, m_depth_bounds_max); glDepthBounds(m_depth_bounds_min, m_depth_bounds_max); checkForGlError("glDepthBounds"); } if(m_set_clip) { //ConLog.Warning("glDepthRangef(%f, %f)", m_clip_min, m_clip_max); glDepthRangef(m_clip_min, m_clip_max); checkForGlError("glDepthRangef"); } if(m_set_line_width) { glLineWidth(m_line_width / 255.f); checkForGlError("glLineWidth"); } if(m_set_blend_equation) { glBlendEquationSeparate(m_blend_equation_rgb, m_blend_equation_alpha); checkForGlError("glBlendEquationSeparate"); } if(m_set_blend_sfactor && m_set_blend_dfactor) { glBlendFuncSeparate(m_blend_sfactor_rgb, m_blend_dfactor_rgb, m_blend_sfactor_alpha, m_blend_dfactor_alpha); checkForGlError("glBlendFuncSeparate"); } if(m_set_blend_color) { glBlendColor(m_blend_color_r, m_blend_color_g, m_blend_color_b, m_blend_color_a); checkForGlError("glBlendColor"); } if(m_set_cull_face) { glCullFace(m_cull_face); checkForGlError("glCullFace"); } if(m_set_alpha_func && m_set_alpha_ref) { glAlphaFunc(m_alpha_func, m_alpha_ref); checkForGlError("glAlphaFunc"); } if(m_set_fog_mode) { glFogi(GL_FOG_MODE, m_fog_mode); checkForGlError("glFogi(GL_FOG_MODE)"); } if(m_set_fog_params) { glFogf(GL_FOG_START, m_fog_param0); checkForGlError("glFogf(GL_FOG_START)"); glFogf(GL_FOG_END, m_fog_param1); checkForGlError("glFogf(GL_FOG_END)"); } if(m_set_restart_index) { ConLog.Warning("m_set_restart_index requires glPrimitiveRestartIndex()"); //glPrimitiveRestartIndex(m_restart_index); //Requires OpenGL 3.1+ //checkForGlError("glPrimitiveRestartIndex"); } if(m_indexed_array.m_count && m_draw_array_count) { ConLog.Warning("m_indexed_array.m_count && draw_array_count"); } for(u32 i=0; i<m_textures_count; ++i) { if(!m_textures[i].IsEnabled()) continue; glActiveTexture(GL_TEXTURE0 + i); checkForGlError("glActiveTexture"); m_gl_textures[i].Create(); m_gl_textures[i].Bind(); checkForGlError(wxString::Format("m_gl_textures[%d].Bind", i)); m_program.SetTex(i); m_gl_textures[i].Init(m_textures[i]); checkForGlError(wxString::Format("m_gl_textures[%d].Init", i)); } m_vao.Bind(); if(m_indexed_array.m_count) { LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1); } EnableVertexData(m_indexed_array.m_count ? true : false); InitVertexData(); InitFragmentData(); if(m_indexed_array.m_count) { switch(m_indexed_array.m_type) { case 0: glDrawElements(m_draw_mode - 1, m_indexed_array.m_count, GL_UNSIGNED_INT, nullptr); checkForGlError("glDrawElements #4"); break; case 1: glDrawElements(m_draw_mode - 1, m_indexed_array.m_count, GL_UNSIGNED_SHORT, nullptr); checkForGlError("glDrawElements #2"); break; default: ConLog.Error("Bad indexed array type (%d)", m_indexed_array.m_type); break; } DisableVertexData(); m_indexed_array.Reset(); } if(m_draw_array_count) { //ConLog.Warning("glDrawArrays(%d,%d,%d)", m_draw_mode - 1, m_draw_array_first, m_draw_array_count); glDrawArrays(m_draw_mode - 1, 0, m_draw_array_count); checkForGlError("glDrawArrays"); DisableVertexData(); } if(Ini.GSDumpColorBuffers.GetValue()) WriteBuffers(); }
// Copies RGBA8 data from RAM to the currently bound render target. void SoftGPU::CopyToCurrentFboFromRam(u8* data, int srcwidth, int srcheight, int dstwidth, int dstheight) { glDisable(GL_BLEND); glViewport(0, 0, dstwidth, dstheight); glScissor(0, 0, dstwidth, dstheight); glBindTexture(GL_TEXTURE_2D, temp_texture); GLfloat texvert_u; if (gstate.FrameBufFormat() == GE_FORMAT_8888) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)gstate.FrameBufStride(), (GLsizei)srcheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); texvert_u = (float)srcwidth / gstate.FrameBufStride(); } else { // TODO: This should probably be converted in a shader instead.. // TODO: Do something less brain damaged to manage this buffer... u32 *buf = new u32[srcwidth * srcheight]; for (int y = 0; y < srcheight; ++y) { u32 *buf_line = &buf[y * srcwidth]; const u16 *fb_line = &fb.as16[y * gstate.FrameBufStride()]; switch (gstate.FrameBufFormat()) { case GE_FORMAT_565: for (int x = 0; x < srcwidth; ++x) { buf_line[x] = DecodeRGB565(fb_line[x]); } break; case GE_FORMAT_5551: for (int x = 0; x < srcwidth; ++x) { buf_line[x] = DecodeRGBA5551(fb_line[x]); } break; case GE_FORMAT_4444: for (int x = 0; x < srcwidth; ++x) { buf_line[x] = DecodeRGBA4444(fb_line[x]); } break; default: ERROR_LOG_REPORT(G3D, "Software: Unexpected framebuffer format: %d", gstate.FrameBufFormat()); } } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)srcwidth, (GLsizei)srcheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); texvert_u = 1.0f; delete[] buf; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glUseProgram(program); static const GLfloat verts[4][2] = { { -1, -1}, // Left top { -1, 1}, // left bottom { 1, 1}, // right bottom { 1, -1} // right top }; const GLfloat texverts[4][2] = { {0, 1}, {0, 0}, {texvert_u, 0}, {texvert_u, 1} }; glVertexAttribPointer(attr_pos, 2, GL_FLOAT, GL_FALSE, 0, verts); glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, texverts); glEnableVertexAttribArray(attr_pos); glEnableVertexAttribArray(attr_tex); glUniform1i(uni_tex, 0); glActiveTexture(GL_TEXTURE0); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableVertexAttribArray(attr_pos); glDisableVertexAttribArray(attr_tex); glBindTexture(GL_TEXTURE_2D, 0); }
static Bool glamor_copy_fbo_fbo_draw(DrawablePtr src, DrawablePtr dst, GCPtr gc, BoxPtr box, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) { ScreenPtr screen = dst->pScreen; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src); PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst); glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap); glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap); int src_box_x, src_box_y, dst_box_x, dst_box_y; int dst_off_x, dst_off_y; int src_off_x, src_off_y; GLshort *v; char *vbo_offset; struct copy_args args; glamor_program *prog; const glamor_facet *copy_facet; Bool set_scissor; int n; glamor_make_current(glamor_priv); if (gc && !glamor_set_planemask(dst_pixmap, gc->planemask)) goto bail_ctx; if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy)) goto bail_ctx; if (bitplane) { prog = &glamor_priv->copy_plane_prog; copy_facet = &glamor_facet_copyplane; } else { prog = &glamor_priv->copy_area_prog; copy_facet = &glamor_facet_copyarea; } if (prog->failed) goto bail_ctx; if (!prog->prog) { if (!glamor_build_program(screen, prog, copy_facet, NULL)) goto bail_ctx; } args.src_pixmap = src_pixmap; args.bitplane = bitplane; /* Set up the vertex buffers for the points */ v = glamor_get_vbo_space(dst->pScreen, nbox * 8 * sizeof (int16_t), &vbo_offset); glEnableVertexAttribArray(GLAMOR_VERTEX_POS); glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, 2 * sizeof (GLshort), vbo_offset); for (n = 0; n < nbox; n++) { v[0] = box->x1; v[1] = box->y1; v[2] = box->x1; v[3] = box->y2; v[4] = box->x2; v[5] = box->y2; v[6] = box->x2; v[7] = box->y1; v += 8; box++; } glamor_put_vbo_space(screen); glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y); set_scissor = src_priv->type == GLAMOR_TEXTURE_LARGE; if (set_scissor) glEnable(GL_SCISSOR_TEST); glamor_pixmap_loop(src_priv, src_box_x, src_box_y) { BoxPtr src_box = glamor_pixmap_box_at(src_priv, src_box_x, src_box_y); args.dx = dx + src_off_x - src_box->x1; args.dy = dy + src_off_y - src_box->y1; args.src = glamor_pixmap_fbo_at(src_priv, src_box_x, src_box_y); if (!glamor_use_program(dst_pixmap, gc, prog, &args)) goto bail_ctx; glamor_pixmap_loop(dst_priv, dst_box_x, dst_box_y) { glamor_set_destination_drawable(dst, dst_box_x, dst_box_y, FALSE, FALSE, prog->matrix_uniform, &dst_off_x, &dst_off_y); if (set_scissor) glScissor(dst_off_x - args.dx, dst_off_y - args.dy, src_box->x2 - src_box->x1, src_box->y2 - src_box->y1); if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) glDrawArrays(GL_QUADS, 0, nbox * 4); else { int i; for (i = 0; i < nbox; i++) glDrawArrays(GL_TRIANGLE_FAN, i*4, 4); } }
void SurfaceSdlGraphicsManager::updateScreen() { #ifdef USE_OPENGL if (_opengl) { if (_overlayVisible) { if (_overlayDirty) { // remove if already exist if (_overlayNumTex > 0) { glDeleteTextures(_overlayNumTex, _overlayTexIds); delete[] _overlayTexIds; _overlayNumTex = 0; } _overlayNumTex = ((_overlayWidth + (BITMAP_TEXTURE_SIZE - 1)) / BITMAP_TEXTURE_SIZE) * ((_overlayHeight + (BITMAP_TEXTURE_SIZE - 1)) / BITMAP_TEXTURE_SIZE); _overlayTexIds = new GLuint[_overlayNumTex]; glGenTextures(_overlayNumTex, _overlayTexIds); for (int i = 0; i < _overlayNumTex; i++) { glBindTexture(GL_TEXTURE_2D, _overlayTexIds[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, BITMAP_TEXTURE_SIZE, BITMAP_TEXTURE_SIZE, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); } glPixelStorei(GL_UNPACK_ALIGNMENT, 2); glPixelStorei(GL_UNPACK_ROW_LENGTH, _overlayWidth); int curTexIdx = 0; for (int y = 0; y < _overlayHeight; y += BITMAP_TEXTURE_SIZE) { for (int x = 0; x < _overlayWidth; x += BITMAP_TEXTURE_SIZE) { int t_width = (x + BITMAP_TEXTURE_SIZE >= _overlayWidth) ? (_overlayWidth - x) : BITMAP_TEXTURE_SIZE; int t_height = (y + BITMAP_TEXTURE_SIZE >= _overlayHeight) ? (_overlayHeight - y) : BITMAP_TEXTURE_SIZE; glBindTexture(GL_TEXTURE_2D, _overlayTexIds[curTexIdx]); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, t_width, t_height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (byte *)_overlayscreen->pixels + (y * 2 * _overlayWidth) + (2 * x)); curTexIdx++; } } glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } // Save current state glPushAttrib(GL_TRANSFORM_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT); // prepare view glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, _overlayWidth, _overlayHeight, 0, 0, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glEnable(GL_SCISSOR_TEST); glScissor(0, 0, _overlayWidth, _overlayHeight); int curTexIdx = 0; for (int y = 0; y < _overlayHeight; y += BITMAP_TEXTURE_SIZE) { for (int x = 0; x < _overlayWidth; x += BITMAP_TEXTURE_SIZE) { glBindTexture(GL_TEXTURE_2D, _overlayTexIds[curTexIdx]); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2i(x, y); glTexCoord2f(1.0f, 0.0f); glVertex2i(x + BITMAP_TEXTURE_SIZE, y); glTexCoord2f(1.0f, 1.0f); glVertex2i(x + BITMAP_TEXTURE_SIZE, y + BITMAP_TEXTURE_SIZE); glTexCoord2f(0.0f, 1.0f); glVertex2i(x, y + BITMAP_TEXTURE_SIZE); glEnd(); curTexIdx++; } } // Restore previous state glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_TEXTURE); glPopMatrix(); glPopAttrib(); } SDL_GL_SwapBuffers(); } else #endif { if (_overlayVisible) { SDL_LockSurface(_screen); SDL_LockSurface(_overlayscreen); Graphics::PixelBuffer srcBuf(_overlayFormat, (byte *)_overlayscreen->pixels); Graphics::PixelBuffer dstBuf(_screenFormat, (byte *)_screen->pixels); int h = _overlayHeight; do { dstBuf.copyBuffer(0, _overlayWidth, srcBuf); srcBuf.shiftBy(_overlayWidth); dstBuf.shiftBy(_overlayWidth); } while (--h); SDL_UnlockSurface(_screen); SDL_UnlockSurface(_overlayscreen); } SDL_Flip(_screen); } }
void nuiGLPainter::SetState(const nuiRenderState& rState, bool ForceApply) { //TEST_FBO_CREATION(); NUI_RETURN_IF_RENDERING_DISABLED; nuiCheckForGLErrors(); // blending if (ForceApply || mState.mBlending != rState.mBlending) { mState.mBlending = rState.mBlending; if (mState.mBlending) { glEnable(GL_BLEND); } else { glDisable(GL_BLEND); } } if (ForceApply || mState.mBlendFunc != rState.mBlendFunc) { mState.mBlendFunc = rState.mBlendFunc; GLenum src, dst; nuiGetBlendFuncFactors(rState.mBlendFunc, src, dst); BlendFuncSeparate(src, dst); nuiCheckForGLErrors(); } if (ForceApply || mState.mDepthTest != rState.mDepthTest) { mState.mDepthTest = rState.mDepthTest; if (mState.mDepthTest) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); } if (ForceApply || mState.mDepthWrite != rState.mDepthWrite) { mState.mDepthWrite = rState.mDepthWrite; glDepthMask(mState.mDepthWrite); } // We don't care about the font in the lower layer of rendering //nuiFont* mpFont; // ApplyTexture(rState, ForceApply); // Rendering buffers: if (ForceApply || mState.mColorBuffer != rState.mColorBuffer) { mState.mColorBuffer = rState.mColorBuffer; GLboolean m = mState.mColorBuffer ? GL_TRUE : GL_FALSE; glColorMask(m, m, m, m); nuiCheckForGLErrors(); } if (mClip.mEnabled || ForceApply) { uint32 width = mWidth; uint32 height = mHeight; if (mpSurface) { width = mpSurface->GetWidth(); height = mpSurface->GetHeight(); } nuiRect clip(mClip); int x,y,w,h; uint angle = (mpSurface && mpSurface->GetRenderToTexture()) ? 0 : mAngle; if (angle == 90) { x = ToBelow(clip.Top()); y = ToBelow(clip.Left()); w = ToBelow(clip.GetHeight()); h = ToBelow(clip.GetWidth()); } else if (angle == 180) { w = ToBelow(clip.GetWidth()); h = ToBelow(clip.GetHeight()); x = ToBelow(width - w - clip.Left()); y = ToBelow(clip.Top()); } else if (angle == 270) { w = ToBelow(clip.GetHeight()); h = ToBelow(clip.GetWidth()); x = ToBelow(height - clip.Top() - w); y = ToBelow(width - clip.Left() - h); } else { NGL_ASSERT(!angle); x = ToBelow(clip.Left()); y = ToBelow(height - clip.Bottom()); w = ToBelow(clip.GetWidth()); h = ToBelow(clip.GetHeight()); } //NGL_OUT(_T("To Screen Clip {%d, %d, %d, %d}\n"), x,y,w,h); if (!mScissorOn || ForceApply) { glEnable(GL_SCISSOR_TEST); mScissorOn = true; } if (mScissorX != x || mScissorY != y || mScissorW != w || mScissorH != h || ForceApply) { mScissorX = x; mScissorY = y; mScissorW = w; mScissorH = h; x *= NUI_SCALE_FACTOR; y *= NUI_SCALE_FACTOR; w *= NUI_SCALE_FACTOR; h *= NUI_SCALE_FACTOR; glScissor(x, y, w, h); } nuiCheckForGLErrors(); } else { if (mScissorOn || ForceApply) { glDisable(GL_SCISSOR_TEST); mScissorOn = false; } } mState.mClearColor = rState.mClearColor; mState.mStrokeColor = rState.mStrokeColor; mState.mFillColor = rState.mFillColor; nuiCheckForGLErrors(); }
void OpenGL3StateChangeWrapper::scissor(GLint x, GLint y, GLsizei width, GLsizei height) { bool callIsRedundant = d_scissorParams.equal(x, y, width, height); if(!callIsRedundant) glScissor(x, y, width, height); }
static void hw_enable_clipper(int x, int y, int w, int h) { glEnable(GL_SCISSOR_TEST); glScissor(x, y, w, h); }
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // If text or lines are blurry when integrating ImGui in your engine: // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x); int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y); if (fb_width == 0 || fb_height == 0) return; draw_data->ScaleClipRects(io.DisplayFramebufferScale); // Backup GL state GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); GLint last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, &last_active_texture); GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); GLint last_blend_src; glGetIntegerv(GL_BLEND_SRC, &last_blend_src); GLint last_blend_dst; glGetIntegerv(GL_BLEND_DST, &last_blend_dst); GLint last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb); GLint last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLboolean last_enable_blend = glIsEnabled(GL_BLEND); GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glActiveTexture(GL_TEXTURE0); // Setup orthographic projection matrix glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); const float ortho_projection[4][4] = { { 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f }, { 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f }, { 0.0f, 0.0f, -1.0f, 0.0f }, {-1.0f, 1.0f, 0.0f, 1.0f }, }; glUseProgram(g_ShaderHandle); glUniform1i(g_AttribLocationTex, 0); glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); glBindVertexArray(g_VaoHandle); for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawIdx* idx_buffer_offset = 0; glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.size() * sizeof(ImDrawVert), (GLvoid*)&cmd_list->VtxBuffer.front(), GL_STREAM_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx), (GLvoid*)&cmd_list->IdxBuffer.front(), GL_STREAM_DRAW); for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) { if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); } idx_buffer_offset += pcmd->ElemCount; } } // Restore modified GL state glUseProgram(last_program); glActiveTexture(last_active_texture); glBindTexture(GL_TEXTURE_2D, last_texture); glBindVertexArray(last_vertex_array); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer); glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); glBlendFunc(last_blend_src, last_blend_dst); if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); }
void CGEDebugger::UpdatePrimPreview(u32 op) { const u32 prim_type = (op >> 16) & 0xFF; int count = op & 0xFFFF; if (prim_type >= 7) { ERROR_LOG(COMMON, "Unsupported prim type: %x", op); return; } if (!gpuDebug) { ERROR_LOG(COMMON, "Invalid debugging environment, shutting down?"); return; } if (count == 0) { return; } const GEPrimitiveType prim = static_cast<GEPrimitiveType>(prim_type); static std::vector<GPUDebugVertex> vertices; static std::vector<u16> indices; if (!gpuDebug->GetCurrentSimpleVertices(count, vertices, indices)) { ERROR_LOG(COMMON, "Vertex preview not yet supported"); return; } if (prim == GE_PRIM_RECTANGLES) { ExpandRectangles(vertices, indices, count, gpuDebug->GetGState().isModeThrough()); } float fw, fh; float x, y; frameWindow->Begin(); frameWindow->GetContentSize(x, y, fw, fh); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); glBindTexture(GL_TEXTURE_2D, 0); glViewport((GLint)x, (GLint)y, (GLsizei)fw, (GLsizei)fh); glScissor((GLint)x, (GLint)y, (GLsizei)fw, (GLsizei)fh); BindPreviewProgram(previewProgram); float scale[] = { 480.0f / (float)PSP_CoreParameter().renderWidth, 272.0f / (float)PSP_CoreParameter().renderHeight, }; Matrix4x4 ortho; ortho.setOrtho(0, frameWindow->TexWidth() * scale[0], frameWindow->TexHeight() * scale[1], 0, -1, 1); glUniformMatrix4fv(previewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr()); glEnableVertexAttribArray(previewProgram->a_position); glVertexAttribPointer(previewProgram->a_position, 3, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data() + 2); if (indices.empty()) { glDrawArrays(glprim[prim], 0, count); } else { glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, indices.data()); } frameWindow->End(); texWindow->Begin(); texWindow->GetContentSize(x, y, fw, fh); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); glBindTexture(GL_TEXTURE_2D, 0); glViewport((GLint)x, (GLint)y, (GLsizei)fw, (GLsizei)fh); glScissor((GLint)x, (GLint)y, (GLsizei)fw, (GLsizei)fh); BindPreviewProgram(texPreviewProgram); // TODO: Probably there's a better way and place to do this. if (indices.empty()) { for (int i = 0; i < count; ++i) { vertices[i].u -= floor(vertices[i].u); vertices[i].v -= floor(vertices[i].v); } } else { for (int i = 0; i < count; ++i) { vertices[indices[i]].u -= floor(vertices[indices[i]].u); vertices[indices[i]].v -= floor(vertices[indices[i]].v); } } ortho.setOrtho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0); glUniformMatrix4fv(texPreviewProgram->u_viewproj, 1, GL_FALSE, ortho.getReadPtr()); glEnableVertexAttribArray(texPreviewProgram->a_position); glVertexAttribPointer(texPreviewProgram->a_position, 2, GL_FLOAT, GL_FALSE, sizeof(GPUDebugVertex), (float *)vertices.data()); if (indices.empty()) { glDrawArrays(glprim[prim], 0, count); } else { glDrawElements(glprim[prim], count, GL_UNSIGNED_SHORT, indices.data()); } texWindow->End(); }
/* Called by GLUT whenever the window needs to be redrawn. This * function should not be called directly by the programmer. Instead, * we can call glutPostRedisplay() to request that GLUT call display() * at some point. */ void display() { /* If we are using DGR, send or receive data to keep multiple * processes/computers synchronized. */ dgr_update(); dgr_setget("style", &renderStyle, sizeof(int)); /* Render the scene once for each viewport. Frequently one * viewport will fill the entire screen. However, this loop will * run twice for HMDs (once for the left eye and once for the * right. */ viewmat_begin_frame(); for(int viewportID=0; viewportID<viewmat_num_viewports(); viewportID++) { viewmat_begin_eye(viewportID); /* Where is the viewport that we are drawing onto and what is its size? */ int viewport[4]; // x,y of lower left corner, width, height viewmat_get_viewport(viewport, viewportID); glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); /* Clear the current viewport. Without glScissor(), glClear() * clears the entire screen. We could call glClear() before * this viewport loop---but on order for all variations of * this code to work (Oculus support, etc), we can only draw * after viewmat_begin_eye(). */ glScissor(viewport[0], viewport[1], viewport[2], viewport[3]); glEnable(GL_SCISSOR_TEST); glClearColor(.2,.2,.2,0); // set clear color to grey glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glDisable(GL_SCISSOR_TEST); glEnable(GL_DEPTH_TEST); // turn on depth testing kuhl_errorcheck(); /* Turn on blending (note, if you are using transparent textures, the transparency may not look correct unless you draw further items before closer items.). */ glEnable(GL_BLEND); glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); /* Get the view or camera matrix; update the frustum values if needed. */ float viewMat[16], perspective[16]; viewmat_get(viewMat, perspective, viewportID); glUseProgram(program); kuhl_errorcheck(); /* Send the perspective projection matrix to the vertex program. */ glUniformMatrix4fv(kuhl_get_uniform("Projection"), 1, // number of 4x4 float matrices 0, // transpose perspective); // value float modelMat[16]; get_model_matrix(modelMat); float modelview[16]; mat4f_mult_mat4f_new(modelview, viewMat, modelMat); // modelview = view * model /* Send the modelview matrix to the vertex program. */ glUniformMatrix4fv(kuhl_get_uniform("ModelView"), 1, // number of 4x4 float matrices 0, // transpose modelview); // value glUniform1i(kuhl_get_uniform("renderStyle"), renderStyle); // Copy far plane value into vertex program so we can render depth buffer. float f[6]; // left, right, bottom, top, near>0, far>0 projmat_get_frustum(f, viewport[2], viewport[3]); glUniform1f(kuhl_get_uniform("farPlane"), f[5]); kuhl_errorcheck(); kuhl_limitfps(60); update(); kuhl_geometry_draw(modelgeom); /* Draw the model */ kuhl_errorcheck(); glUseProgram(0); // stop using a GLSL program. } // finish viewport loop viewmat_end_frame(); /* Check for errors. If there are errors, consider adding more * calls to kuhl_errorcheck() in your code. */ kuhl_errorcheck(); // kuhl_video_record("videoout", 30); /* Ask GLUT to call display() again. We shouldn't call display() * ourselves recursively because it will not leave time for GLUT * to call other callback functions for when a key is pressed, the * window is resized, etc. */ glutPostRedisplay(); }
void APIENTRY ScissorIndexed(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height) { glScissor(left, bottom, width, height); }
void LayerBase::drawWithOpenGL(const Region& clip, GLint textureName, const GGLSurface& t) const { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const uint32_t fbHeight = hw.getHeight(); const State& s(drawingState()); // bind our texture validateTexture(textureName); glEnable(GL_TEXTURE_2D); // Dithering... if (s.flags & ISurfaceComposer::eLayerDither) { glEnable(GL_DITHER); } else { glDisable(GL_DITHER); } if (UNLIKELY(s.alpha < 0xFF)) { // We have an alpha-modulation. We need to modulate all // texture components by alpha because we're always using // premultiplied alpha. // If the texture doesn't have an alpha channel we can // use REPLACE and switch to non premultiplied alpha // blending (SRCA/ONE_MINUS_SRCA). GLenum env, src; if (needsBlending()) { env = GL_MODULATE; src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA; } else { env = GL_REPLACE; src = GL_SRC_ALPHA; } const GGLfixed alpha = (s.alpha << 16)/255; glColor4x(alpha, alpha, alpha, alpha); glEnable(GL_BLEND); glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env); } else { glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glColor4x(0x10000, 0x10000, 0x10000, 0x10000); if (needsBlending()) { GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA; glEnable(GL_BLEND); glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA); } else { glDisable(GL_BLEND); } } if (UNLIKELY(transformed() || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) { //StopWatch watch("GL transformed"); Region::iterator iterator(clip); if (iterator) { // always use high-quality filtering with fast configurations bool fast = !(mFlags & DisplayHardware::SLOW_CONFIG); if (!fast && s.flags & ISurfaceComposer::eLayerFilter) { glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } const GLfixed texCoords[4][2] = { { 0, 0 }, { 0, 0x10000 }, { 0x10000, 0x10000 }, { 0x10000, 0 } }; glMatrixMode(GL_TEXTURE); glLoadIdentity(); if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { // find the smallest power-of-two that will accommodate our surface GLuint tw = 1 << (31 - clz(t.width)); GLuint th = 1 << (31 - clz(t.height)); if (tw < t.width) tw <<= 1; if (th < t.height) th <<= 1; // this divide should be relatively fast because it's // a power-of-two (optimized path in libgcc) GLfloat ws = GLfloat(t.width) /tw; GLfloat hs = GLfloat(t.height)/th; glScalef(ws, hs, 1.0f); } glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(2, GL_FIXED, 0, mVertices); glTexCoordPointer(2, GL_FIXED, 0, texCoords); Rect r; while (iterator.iterate(&r)) { const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } if (!fast && s.flags & ISurfaceComposer::eLayerFilter) { glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } else { Region::iterator iterator(clip); if (iterator) { Rect r; GLint crop[4] = { 0, t.height, t.width, -t.height }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); int x = tx(); int y = ty(); y = fbHeight - (y + t.height); while (iterator.iterate(&r)) { const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawTexiOES(x, y, 0, t.width, t.height); } } } }
void SceneRenderer::render( bool _lastFrame, bool _sameFrame, bool fullWindow) { static const GLfloat blindnessColor[4] = { 1.0f, 1.0f, 0.0f, 1.0f }; static const GLfloat dimnessColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; static const float dimDensity = 0.75f; bool lighting = BZDB.isTrue("lighting"); lastFrame = _lastFrame; sameFrame = _sameFrame; // avoid OpenGL calls as long as possible -- there's a good // chance we're waiting on the vertical retrace. // set the view frustum if (sceneIterator) sceneIterator->resetFrustum(&frustum); // get the important lights in the scene int i; int numLights = 0; if (!sameFrame) { clearLights(); if (sceneIterator && !blank && lighting) { // add lights sceneIterator->reset(); SceneNode* node; while ((node = sceneIterator->getNext()) != NULL) node->addLight(*this); numLights = lights.size(); // pick maxLights most important light sources // should go by full lighting function but we'll just go by distance if (numLights > maxLights) { const GLfloat* eye = frustum.getEye(); for (i = 0; i < maxLights; i++) { GLfloat maxImportance = lights[i]->getImportance(eye); for (int j = i + 1; j < numLights; j++) { GLfloat importance = lights[j]->getImportance(eye); if (importance > maxImportance) { OpenGLLight* temp = lights[i]; lights[j] = lights[i]; lights[i] = temp; maxImportance = importance; } } } numLights = maxLights; } } } // get the nodes to draw if (!blank) { // empty the render node lists in preparation for the next frame OpenGLGState::clearLists(); orderedList.clear(); shadowList.clear(); flareLightList.clear(); // make the lists of render nodes sorted in optimal rendering order if (sceneIterator) { sceneIterator->reset(); SceneNode* node; while ((node = sceneIterator->getNext()) != NULL) node->getRenderNodes(*this); } // sort ordered list in reverse depth order if (!inOrder) orderedList.sort(frustum.getEye()); } // prepare transforms // note -- lights should not be positioned before view is set frustum.executeDeepProjection(); glPushMatrix(); frustum.executeView(); // turn sunlight on -- the ground needs it if (lighting && sunOrMoonUp) { theSun.execute(SunLight); theSun.enableLight(SunLight); } // turn on fog for teleporter blindness if close to a teleporter float teleporterProximity = 0.0f; if (!blank && LocalPlayer::getMyTank() && (LocalPlayer::getMyTank()->getTeam() != ObserverTeam)) teleporterProximity = LocalPlayer::getMyTank()->getTeleporterProximity(); float worldSize = BZDB.eval(StateDatabase::BZDB_WORLDSIZE); bool reallyUseFogHack = useFogHack && (useQualityValue >= 2); if (reallyUseFogHack) { if (useDimming) { const float density = dimDensity; glFogi(GL_FOG_MODE, GL_LINEAR); glFogf(GL_FOG_START, -density * 1000.0f * worldSize); glFogf(GL_FOG_END, (1.0f - density) * 1000.0f * worldSize); glFogfv(GL_FOG_COLOR, dimnessColor); glEnable(GL_FOG); } else if (teleporterProximity > 0.0f && useFogHack) { const float density = (teleporterProximity > 0.75f) ? 1.0f : teleporterProximity / 0.75f; glFogi(GL_FOG_MODE, GL_LINEAR); glFogf(GL_FOG_START, -density * 1000.0f * worldSize); glFogf(GL_FOG_END, (1.0f - density) * 1000.0f * worldSize); glFogfv(GL_FOG_COLOR, blindnessColor); glEnable(GL_FOG); } } // set scissor glScissor(window.getOriginX(), window.getOriginY() + window.getHeight() - window.getViewHeight(), window.getWidth(), window.getViewHeight()); if (useDepthComplexityOn) { // glEnable(GL_STENCIL_TEST); // glClear(GL_STENCIL_BUFFER_BIT); // glStencilFunc(GL_ALWAYS, 0, 0xf); // glStencilOp(GL_KEEP, GL_INCR, GL_INCR); } if (useHiddenLineOn) { //glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // glClear(GL_COLOR_BUFFER_BIT); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } else if (useWireframeOn) { //glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // glClear(GL_COLOR_BUFFER_BIT); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } // prepare z buffer /* if (BZDB.isTrue("zbuffer")) { if (sameFrame && ++depthRange == numDepthRanges) depthRange = 0; if (exposed || useHiddenLineOn || --depthRange < 0) { depthRange = numDepthRanges - 1; glClear(GL_DEPTH_BUFFER_BIT); exposed = false; } if (!sameFrame && numDepthRanges != 1) { if (useHiddenLineOn) { glDepthRange(0.0, 1.0); } else { GLclampd x_near = (GLclampd)depthRange * depthRangeSize; glDepthRange(x_near, x_near + depthRangeSize); } } } */ // draw start of background (no depth testing) OpenGLGState::resetState(); if (background) { background->setBlank(blank); background->setInvert(invert); background->renderSkyAndGround(*this, fullWindow); } // prepare the other lights but don't turn them on yet -- // we may need to turn them on when drawing the background. if (lighting) { for (i = 0; i < numLights; i++) lights[i]->execute(i + reservedLights); } // draw rest of background if (background) background->render(*this); if (!blank) { if (lighting) { // now turn on the remaining lights for (i = 0; i < numLights; i++) OpenGLLight::enableLight(i + reservedLights); } frustum.executeProjection(); if (BZDB.isTrue("zbuffer")) glEnable(GL_DEPTH_TEST); if (useHiddenLineOn) { #if defined(GL_VERSION_1_1) glEnable(GL_POLYGON_OFFSET_FILL); #elif defined(GL_EXT_polygon_offset) glEnable(GL_POLYGON_OFFSET_EXT); #endif } // render the normal stuff doRender(); if (useHiddenLineOn) { #if defined(GL_VERSION_1_1) glDisable(GL_POLYGON_OFFSET_FILL); #elif defined(GL_EXT_polygon_offset) glDisable(GL_POLYGON_OFFSET_EXT); #endif glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); doRender(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } OpenGLGState::resetState(); // shut off lights if (lighting) { theSun.enableLight(SunLight, false); for (i = 0; i < numLights; i++) OpenGLLight::enableLight(i + reservedLights, false); } if (BZDB.isTrue("zbuffer")) glDisable(GL_DEPTH_TEST); // FIXME -- must do post-rendering: flare lights, etc. // flare lights are in world coordinates. trace ray to that world // position and calculate opacity. if opaque then don't render // flare, otherwise modulate input color by opacity and draw a // billboard texture (constant size in screen space). } // back to original state if (!useHiddenLineOn && useWireframeOn) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPopMatrix(); if ((reallyUseFogHack && (teleporterProximity > 0.0f || useDimming))) glDisable(GL_FOG); if (!reallyUseFogHack) { float density = 0.0f; const GLfloat* color = NULL; if (useDimming) { density = dimDensity; color = dimnessColor; } else if (teleporterProximity > 0.0f) { density = (teleporterProximity > 0.75f) ? 1.0f : teleporterProximity / 0.75f; color = blindnessColor; } if (density > 0.0f && color != NULL) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glColor4f(color[0], color[1], color[2], density); glRectf(-1.0f, -1.0f, 1.0f, 1.0f); } } if (useDepthComplexityOn) { static const GLfloat depthColors[][3] = { { 0.0f, 0.0f, 0.0f }, // black -- 0 times { 0.5f, 0.0f, 1.0f }, // purple -- 1 time { 0.0f, 0.0f, 1.0f }, // blue -- 2 times { 0.0f, 1.0f, 1.0f }, // cyan -- 3 times { 0.0f, 1.0f, 0.0f }, // green -- 4 times { 1.0f, 1.0f, 0.0f }, // yellow -- 5 times { 1.0f, 0.5f, 0.0f }, // orange -- 6 times { 1.0f, 0.0f, 0.0f } // red -- 7 or more }; static const int numColors = countof(depthColors); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); for (i = 0; i < numColors; i++) { glStencilFunc(i == numColors - 1 ? GL_LEQUAL : GL_EQUAL, i, 0xf); glColor3fv(depthColors[i]); glRectf(-1.0f, -1.0f, 1.0f, 1.0f); } glDisable(GL_STENCIL_TEST); } }
bool BootAnimation::android() { initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png"); // clear screen glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(mDisplay, mSurface); glEnable(GL_TEXTURE_2D); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const GLint xc = (mWidth - mAndroid[0].w) / 2; const GLint yc = (mHeight - mAndroid[0].h) / 2; const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), updateRect.height()); // Blend state glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const nsecs_t startTime = systemTime(); do { nsecs_t now = systemTime(); double time = now - startTime; float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w; GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w; GLint x = xc - offset; glDisable(GL_SCISSOR_TEST); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_SCISSOR_TEST); glDisable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h); glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h); glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h); EGLBoolean res = eglSwapBuffers(mDisplay, mSurface); if (res == EGL_FALSE) break; // 12fps: don't animate too fast to preserve CPU const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now); if (sleepTime > 0) usleep(sleepTime); checkExit(); } while (!exitPending()); glDeleteTextures(1, &mAndroid[0].name); glDeleteTextures(1, &mAndroid[1].name); return false; }
void ImGui_Wrapper::renderGui() { glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glActiveTexture(GL_TEXTURE0); ImGuiIO& io = ImGui::GetIO(); int fb_width = static_cast<GLsizei>(io.DisplaySize.x); int fb_height = static_cast<GLsizei>(io.DisplaySize.y); glViewport(0, 0, fb_width, fb_height); const float ortho_projection[4][4] = { { 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f }, { 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f }, { 0.0f, 0.0f, -1.0f, 0.0f }, {-1.0f, 1.0f, 0.0f, 1.0f }, }; m_shader.bind(); m_shader.setUniformValue(m_locationTex, 0); m_shader.setUniformValueMat4(m_locationProjMtx, &ortho_projection[0][0]); m_VAO.bind(); const auto draw_data = ImGui::GetDrawData(); for (int n = 0; n < draw_data->CmdListsCount; ++n) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawIdx* idx_buffer_offset = nullptr; m_VBO.bind(); m_VBO.write(0, &cmd_list->VtxBuffer.front(), cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); m_EBO.bind(); m_EBO.write(0, &cmd_list->IdxBuffer.front(), cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx)); for (const ImDrawCmd& pcmd : cmd_list->CmdBuffer) { if (pcmd.UserCallback) pcmd.UserCallback(cmd_list, &pcmd); else { glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(reinterpret_cast<intptr_t>(pcmd.TextureId))); glScissor(static_cast<int>(pcmd.ClipRect.x), fb_height - static_cast<int>(pcmd.ClipRect.w), static_cast<int>(pcmd.ClipRect.z - pcmd.ClipRect.x), static_cast<int>(pcmd.ClipRect.w - pcmd.ClipRect.y)); glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(pcmd.ElemCount), sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); } idx_buffer_offset += pcmd.ElemCount; } } m_shader.release(); m_VAO.release(); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); }
// OpenGL2 Render function. // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. void ImGui_ImplSdlGL2_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x); int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y); if (fb_width == 0 || fb_height == 0) return; draw_data->ScaleClipRects(io.DisplayFramebufferScale); // We are using the OpenGL fixed pipeline to make the example code simpler to read! // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill. GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_SCISSOR_TEST); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnable(GL_TEXTURE_2D); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound // Setup viewport, orthographic projection matrix glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); // Render command lists for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos))); glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv))); glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col))); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer); } idx_buffer += pcmd->ElemCount; } } // Restore modified state glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); }
void device_setscissorrect(device_t device, struct gs_rect *rect) { glScissor(rect->x, rect->y, rect->cx, rect->cy); if (!gl_success("glScissor")) blog(LOG_ERROR, "device_setscissorrect (GL) failed"); }