zoukankan      html  css  js  c++  java
  • SDL2笔记06_SDL2透明背景窗口_win10_使用cairo和sdl_texture在透明背景上绘制(偏色)

    1. 这篇git提供了简单的cairo绘制到sdlTexture上的方法
      https://gist.github.com/sprae/607305450c51ccc482b78bdadadb9af6链接

    2. 配置makefile

           cmake_minimum_required(VERSION 3.19)
           project(main)
           set(SDL2_DIR G:/Xubuntu_Work_Space/From_Xubuntu/codeTest_2019_2_21/SDL2/win/SDL2-devel-2.0.14-mingw/SDL2-2.0.14/x86_64-w64-mingw32)
           set(SDL2_IMAGE_DIR G:/Xubuntu_Work_Space/From_Xubuntu/codeTest_2019_2_21/SDL2/win/SDL2_image-devel-2.0.5-mingw/SDL2_image-2.0.5/x86_64-w64-mingw32)
      
           set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -lmingw32")
           set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")
      
           # GTK3的include
           include_directories(
                   H:/mysoft/clion/clionWorkSpace/gtk+364/include
                   H:/mysoft/clion/clionWorkSpace/gtk+364/include/gtk-3.0
                   H:/mysoft/clion/clionWorkSpace/gtk+364/include/cairo
                   H:/mysoft/clion/clionWorkSpace/gtk+364/include/gdk
                   H:/mysoft/clion/clionWorkSpace/gtk+364/include/glib-2.0
                   H:/mysoft/clion/clionWorkSpace/gtk+364/include/pango-1.0
                   H:/mysoft/clion/clionWorkSpace/gtk+364/include/atk-1.0
                   H:/mysoft/clion/clionWorkSpace/gtk+364/include/gdk-pixbuf-2.0
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/glib-2.0/include
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/gtk-3.0/include
           )
      
           # SDL2的include
           include_directories(
                   ${SDL2_DIR}/include/SDL2
                   ${SDL2_IMAGE_DIR}/include/SDL2
           )
      
           link_directories(
                   ${SDL2_DIR}/lib
                   ${SDL2_IMAGE_DIR}/lib
           )
      
           link_libraries(
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libatk-1.0.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libcairo-gobject.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libcairo-script-interpreter.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libcairo.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libcroco-0.6.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libffi.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libfontconfig.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libfreetype.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgailutil-3.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgdk-3.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgdk_pixbuf-2.0.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgio-2.0.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libglib-2.0.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgmodule-2.0.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgobject-2.0.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgthread-2.0.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libgtk-3.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libjasper.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libjpeg.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/liblzma.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpango-1.0.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpangocairo-1.0.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpangoft2-1.0.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpangowin32-1.0.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpixman-1.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpng.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libpng15.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/librsvg-2.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libtiff.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libtiffxx.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libxml2.dll.a
                   H:/mysoft/clion/clionWorkSpace/gtk+364/lib/libz.dll.a
           )
      
           set(SOURCE_FILES main.cpp TransparentWindow.hpp)
           add_executable(main ${SOURCE_FILES})
      
           target_link_libraries(main mingw32 SDL2main SDL2 SDL2_image)
      
      
    3. 第一步:windows将SDL_Window背景设为透明,可直接调用windowColorKey代码

          COLORREF defaultTransparentColor = RGB(255, 0, 255);
       	
       	bool windowColorKey(SDL_Window *window, COLORREF colorKey) {
       	    SDL_SysWMinfo wmInfo;
       	    SDL_VERSION(&wmInfo.version);  // Initialize wmInfo
       	    SDL_GetWindowWMInfo(window, &wmInfo);
       	    HWND hWnd = wmInfo.info.win.window;
       	
       	    // Change window type to layered
       	    SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
       	
       	    // Set transparency color
       	    return SetLayeredWindowAttributes(hWnd, colorKey, 0, LWA_COLORKEY);
       	}
      
    4. 第二步,绑定cairosdlTexture,有两种方式可用(缺点:当画笔大小为1的时候颜色不对,不知怎么解决

      1. 方式一 : 建立cairo, 建立texture, 在cairo上画图,然后update过去
        // 方式一 : 建立cairo, 建立texture, 在cairo上画图,然后update过去
        int windowWidth = 640, windowHeight = 480;
        surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, windowWidth, windowWidth);
        cr = cairo_create(surface);
        cairo_set_line_width(cr, 1);
        // 画个圆角矩形, 发现颜色不对
        cairo_set_source_rgba(cr, 1, 0, 0, 1);
        draw_round_rectangle(cr, 100, 100, 180, 120, 10);
        
        cairo_stroke(cr);
        unsigned char *data = cairo_image_surface_get_data(surface);
        
        SDL_Texture *texture;
        SDL_Rect rect = {.x=0, .y=0, .w=windowWidth, .h=windowHeight};
        
        texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, windowWidth,
                                    windowHeight);
        // 设置texture为混合模式
        SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
        int widthPitch = windowWidth << 2;
        // 更新过去
        SDL_UpdateTexture(texture, &rect, data, widthPitch);
        
      2. 方式二:直接建立sdlTexture然后从sdlTexture的像素数据建立cairo
            // 方式二 : 建立texture, 从texture的像素数据建立cairo, 直接画到texture上去
            // 可能比方式一快, 我没读过cairo_image_surface_create_for_data的源码,不敢妄下定论
            SDL_Texture *texture;
            SDL_Rect rect = {.x=0, .y=0, .w=640, .h=480};
        
            texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, rect.w, rect.h);
            SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
        
            void *pixel;
            int pitch = 4*rect.w; // 一行的像素字节  ARGB32=4 byte, w = 640
            SDL_LockTexture(texture, &rect, &pixel, &pitch);
            surface = cairo_image_surface_create_for_data(
                    (unsigned char*) pixel,
                    CAIRO_FORMAT_ARGB32, rect.w, rect.h, pitch
                    );
            SDL_UnlockTexture(texture);
            cr = cairo_create(surface);
            cairo_set_line_width(cr, 10);
            cairo_set_source_rgb(cr, 255, 0, 0);
            draw_round_rectangle(cr, 100, 100, 50, 60, 10);
            cairo_stroke(cr);
        
    5. 完整代码

       	#include <SDL.h>
       	#include <cairo.h>
       	#include <SDL_syswm.h>
       	#include "windows.h"
       	
       	COLORREF defaultTransparentColor = RGB(255, 0, 255);
       	
       	bool windowColorKey(SDL_Window *window, COLORREF colorKey) {
       	    SDL_SysWMinfo wmInfo;
       	    SDL_VERSION(&wmInfo.version);  // Initialize wmInfo
       	    SDL_GetWindowWMInfo(window, &wmInfo);
       	    HWND hWnd = wmInfo.info.win.window;
       	
       	    // Change window type to layered
       	    SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
       	
       	    // Set transparency color
       	    return SetLayeredWindowAttributes(hWnd, colorKey, 0, LWA_COLORKEY);
       	}
       	
       	static void
       	draw_round_rectangle(cairo_t *cr,
       	                     double x, double y,
       	                     double width, double height, double r) {
       	    cairo_move_to(cr, x + r, y);
       	    cairo_line_to(cr, x + width - r, y);
       	
       	    cairo_move_to(cr, x + width, y + r);
       	    cairo_line_to(cr, x + width, y + height - r);
       	
       	    cairo_move_to(cr, x + width - r, y + height);
       	    cairo_line_to(cr, x + r, y + height);
       	
       	    cairo_move_to(cr, x, y + height - r);
       	    cairo_line_to(cr, x, y + r);
       	
       	    cairo_arc(cr, x + r, y + r, r, M_PI, 3 * M_PI / 2.0);
       	    cairo_arc(cr, x + width - r, y + r, r, 3 * M_PI / 2, 2 * M_PI);
       	    cairo_arc(cr, x + width - r, y + height - r, r, 0, M_PI / 2);
       	    cairo_arc(cr, x + r, y + height - r, r, M_PI / 2, M_PI);
       	}
       	
       	int main(int argc, char *argv[]) {
       	    SDL_Init(SDL_INIT_VIDEO);
       	
       	    SDL_Window *window;
       	    SDL_Renderer *renderer;
       	    SDL_CreateWindowAndRenderer(640, 480, SDL_WINDOW_ALWAYS_ON_TOP, &window, &renderer);
       	    windowColorKey(window, defaultTransparentColor);
       	    SDL_SetWindowTitle(window, "Cairo test");
       	
       	    cairo_surface_t *surface;
       	    cairo_t *cr;
       	#if 1
       	    // 方式一 : 建立cairo, 建立texture, 在cairo上画图,然后update过去
       	    int windowWidth = 640, windowHeight = 480;
       	    surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, windowWidth, windowWidth);
       	    cr = cairo_create(surface);
       	    cairo_set_line_width(cr, 1);
       	    // 画个圆角矩形, 发现颜色不对
       	    cairo_set_source_rgba(cr, 1, 0, 0, 1);
       	    draw_round_rectangle(cr, 100, 100, 180, 120, 10);
       	
       	    cairo_stroke(cr);
       	    unsigned char *data = cairo_image_surface_get_data(surface);
       	
       	    SDL_Texture *texture;
       	    SDL_Rect rect = {.x=0, .y=0, .w=windowWidth, .h=windowHeight};
       	
       	    texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, windowWidth,
       	                                windowHeight);
       	    // 设置texture为混合模式
       	    SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
       	    int widthPitch = windowWidth << 2;
       	    // 更新过去
       	    SDL_UpdateTexture(texture, &rect, data, widthPitch);
       	#else
       	    // 方式二 : 建立texture, 从texture的像素数据建立cairo, 直接画到texture上去
       	    // 可能比方式一快, 我没读过cairo_image_surface_create_for_data的源码,不敢妄下定论
       	    SDL_Texture *texture;
       	    SDL_Rect rect = {.x=0, .y=0, .w=640, .h=480};
       	
       	    texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, rect.w, rect.h);
       	    SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
       	
       	    void *pixel;
       	    int pitch = 4*rect.w; // 一行的像素字节  ARGB32=4 byte, w = 640
       	    SDL_LockTexture(texture, &rect, &pixel, &pitch);
       	    surface = cairo_image_surface_create_for_data(
       	            (unsigned char*) pixel,
       	            CAIRO_FORMAT_ARGB32, rect.w, rect.h, pitch
       	            );
       	    SDL_UnlockTexture(texture);
       	    cr = cairo_create(surface);
       	    cairo_set_line_width(cr, 10);
       	    cairo_set_source_rgb(cr, 255, 0, 0);
       	    draw_round_rectangle(cr, 100, 100, 50, 60, 10);
       	    cairo_stroke(cr);
       	#endif
       	
       	    SDL_Event event;
       	    bool is_working = true;
       	    while (is_working) {
       	        while (SDL_PollEvent(&event)) {
       	            switch (event.type) {
       	                case SDL_QUIT:
       	                    SDL_DestroyWindow(window);
       	                    SDL_DestroyRenderer(renderer);
       	                    SDL_Quit();
       	                    is_working = false;
       	                    break;
       	            }
       	        }
       	
       	        SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255);
       	        SDL_RenderClear(renderer);
       	        SDL_RenderCopy(renderer, texture, NULL, NULL);
       	        SDL_RenderPresent(renderer);
       	        SDL_Delay(66);
       	    }
       	
       	    return 0;
       	}
      
      
    6. 运行截图

  • 相关阅读:
    深入研究Node.js的底层原理和高级使用
    Node.js实际案例分享
    Node.js的下载、安装、配置、Hello World、文档阅读
    Node.js初识
    sphinx初识
    Yii2中后台用前台的代码设置验证码显示不出来?
    彻底解决Yii2中网页刷新时验证码不刷新的问题
    yii2高级模板使用一个域名管理前后台
    Shot(三分)
    遮挡判断(模拟)
  • 原文地址:https://www.cnblogs.com/majiao61/p/15201070.html
Copyright © 2011-2022 走看看