This A8-demo grabs the image of the desktop during startup, shows it on a panel and applies a realtime shader on it, producing a fish-eye effect at the position of the mouse cursor. The download comes with the source and the binaries, ready to run.

Overview

Essentially, the demo introduces a new function called BMAP* bmap_for_desktop(), which returns a newly created BMAP*, that holds the image of the desktop. The function shows how to create a device context of the entire desktop, including the Windows bar and everything, how a Windows bitmap is created that is compatible with the desktop device context, in later the desktop content is blitted into. Then, all pixels are transferred one by one and it is shown, how pixels can be fetched from a Windows bitmap and how the result can be transformed into single R, G and B components.

The other part of the demo is just a nice example of how to use the bmap_process function of Gamestudio, which processes a bitmap with a HLSL (DX9) pixel shader. In this case, I programmed a fish-eye effect, which is located at the mouse cursor position. In addition, the sky changes its color permanently and modulates the fish-eye transformed desktop image, while 3D models of cubes with the A8 sign are falling down.

Core features

  • New function: BMAP* bmap_for_desktop() Lite-C required
  • The demo is compatible to A8.20.1 and upwards (because of bmap_process)
  • Fisheye post-processing effect, with no dependencies
  • Free to use in any project (MIT license)

Latest release

All releases include the corresponding Lite-C and HLSL shaders sources and the demos with their sources, binaries (compiled and ready-to-run), as well as all used artwork.

Desktop Grabbing Demo

src + bin V 0.1 - ∼2 MB - July 2012

Sources

In the following, the sources of the function BMAP* bmap_for_desktop() and the HLSL fisheye post-processing (DX9 HLSL) effect are shown; the source of the whole demo, can be downloaded from the Download tab.

This function uses some device context- and bitmap functions from the Windows API, to blit the desktop content into a Windows bitmap and from there into a Gamestudio BMAP*. The comments are pretty self-explanatory; I added links to the MSDN-pages for particular functions, which I used here. If you have trouble with the Gamestudio functions, please read the online manual.


#include <windows.h>

// Grabs the entire desktop. Make sure to set video_alpha to 0 before and to 100 after,
// to grab the desktop without the engine. Returns a BMAP* with the grabbed desktop.
//
BMAP* bmap_for_desktop ()
{
    BMAP* bmap = NULL;
    
    // get the device context of the entire desktop, including windows bar and everything
    HDC hDesktopDC = GetWindowDC(HWND_DESKTOP);
    if (hDesktopDC != 0)
    {
        // get desktop size in pixels
        int desktopSizeX = GetSystemMetrics(SM_CXSCREEN);
        int desktopSizeY = GetSystemMetrics(SM_CYSCREEN);

        // creates a bitmap compatible with the desktop device context, in which we will later
        // blit the desktop content into
        
        HBITMAP hBitmap = CreateCompatibleBitmap(hDesktopDC, desktopSizeX, desktopSizeY);
        if (hBitmap != NULL)
        {
            // create a memory device context compatible with the device context of the desktop. This
            // context will be used to select the blit target
            HDC hBitmapdc = CreateCompatibleDC(hDesktopDC);
            
            // select the target bitmap into a the desktop-alike device context and copy the desktop
            SelectObject(hBitmapdc, hBitmap);
            BitBlt(hBitmapdc, 0, 0, desktopSizeX, desktopSizeY, hDesktopDC, 0, 0, SRCCOPY);
            
            // create Gamestudio bitmap with size of the desktop
            bmap = bmap_createblack(desktopSizeX, desktopSizeY, 888);
            if (bmap != NULL)
            {
                // lock bitmap to blit from windows bitmap to Gamestudio bitmap
                var format = bmap_lock(bmap, 0);
                if (format > 0)
                {
                    // we blit the bitmap pixelwise by fetching and converting the RGB components from the
                    // Windows bitmap and throwing it with pixel_to_bmap into the Gamestudio bitmap. This
                    // procedure might be faster by using GetDIBits and bmap->finalbits, but this seems to be
                    // safer for now
                    
                    int iRow, iCol;
                    COLORREF colorRef;
                    COLOR color;
                    var pixel;
                    
                    for (iRow = 0; iRow < bmap->height; iRow++)
                    {
                        for (iCol = 0; iCol < bmap->width; iCol++)
                        {
                            // retrieve the RGB color value as of the pixel at the specified coordinate as hexadecimal
                            // value 0x00bbggrr. We use the standard GDI macros to extract the component
                            colorRef = GetPixel(hBitmapdc, iCol, iRow);
                            
                            if (colorRef != CLR_INVALID)
                            {
                                color.red = GetRValue(colorRef);
                                color.green = GetGValue(colorRef);
                                color.blue =  GetBValue(colorRef);
                            }
                            // else: the pixel is outside of the current clipping region
                            
                            // convert and set the retrieved color to a pixel in the format of the Gamestudio bitmap
                            pixel = pixel_for_vec(&color, 100, format);
                            pixel_to_bmap(bmap, iCol, iRow, pixel);
                        }
                    }
                    
                    // blitting done, unlock Gamestudio bitmap
                    bmap_unlock(bmap);
                }
            }
            
            // lets delete the desktop-alike device context
            DeleteDC(hBitmapdc);		
        }
        
        // an application must not -delete- a DC whose handle was obtained by calling the GetDC
        // function. Instead, it must call the ReleaseDC function to free the DC. If such a DC is
        // not freed, serious effects on painting requested by other applications can happen!
        ReleaseDC(HWND_DESKTOP, hDesktopDC);
    }
    
    return(bmap);
}

This effect is simple. The (global) 4-element vector g_lens_flt holds in its .xy component the normalized position of the mouse cursor in UV coordinates of the bitmap. In its .z and .w components, some values are stored, which are used for refraction and the size of the lens effect. The pixelshader itself projects the relative position of the pixel to the cursor position on a hemisphere and uses exp2 on the dot-product to stretch the position, from which we sample from the source bitmap, to create the fisheye look. For the demo, I played with the length of the distortion vector as translucency component (note, that AlphaBlendEnable is turned on).


Texture TargetMap;
sampler2D smp = sampler_state { texture = <TargetMap>; };

float4 g_lens_flt; // x,y, refraction, size
float4 vecViewPort;

float4 PS (float2 uv : TEXCOORD0) : COLOR0 
{ 
  float3 hemisphere = float3(((uv * 2 - 1) - (g_lens_flt.xy * 2 - 1)) / g_lens_flt.w, 0.5);
  float distortion = g_lens_flt.z * exp2(-dot(hemisphere.xy, hemisphere.xy));
  
  return(float4(tex2D(smp, uv - distortion * normalize(hemisphere).xy).rgb, 1 - 0.5 * length(hemisphere)));
}

technique t {
  pass p {
	 AlphaBlendEnable = true;	
	 VertexShader = null;
	 PixelShader = compile ps_2_0 PS();
  }
}

License

Desktop Grabbing Demo (with falling A8 cubes and colored sky)
Copyright © 2012 by Christian Behrenberg (HeelX)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Do you like this project?

donate via PayPal see Amazon wishlist