Author Topic: Feature: Multisampling/Antialiasing  (Read 4662 times)

jitspoe

  • Administrator
  • Autococker
  • Posts: 18802
Feature: Multisampling/Antialiasing
« on: May 29, 2013, 01:34:24 PM »
Add a video options for antialiasing (aka multisampling).

Adding some code reference:

http://forums.inside3d.com/viewtopic.php?f=3&t=5204

Code: [Select]
vmode_t VID_Local_GetDesktopProperties (void)
{
   DEVMODE   devmode;
   vmode_t desktop = {0};

   if (!EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &devmode))
   {
      Sys_Error ("VID_UpdateDesktopProperties: EnumDisplaySettings failed\n");
      return desktop;
   }

   desktop.type      =   MODE_FULLSCREEN;
   desktop.width      =   devmode.dmPelsWidth;
   desktop.height      =   devmode.dmPelsHeight;
   desktop.bpp         =   devmode.dmBitsPerPel;
   
   return desktop;
}

Code: [Select]
  if (wplat.hwnd_dialog)
   {
      if (vid_multisample.value)
      {
         // Poke into it for the PFD
         HDC   hdc         = GetDC(wplat.hwnd_dialog);
         int unused      = WIN_SetupPixelFormat (hdc);
         HGLRC wglHRC   = wglCreateContext( hdc );
         HDC wglHDC       = wglGetCurrentDC();
         int unused2      = wglMakeCurrent( hdc, wglHRC);
         int ask_samples   = (int)vid_multisample.value;

         if (ask_samples != 2 && ask_samples != 4 && ask_samples != 8)
         {
            Con_Warning ("Multisamples requested \"%i\" is invalid, trying 4\n", ask_samples);
            ask_samples = 4;
         }

         // Do it.  We already have desktop properties
         wplat.multisamples = WIN_InitMultisample (wplat.hInstance, wplat.hwnd_dialog, wplat.pfd, ask_samples, &wplat.forcePixelFormat);

         // Your mission is complete.  You may leave now ...     
         wglMakeCurrent(NULL, NULL);
         wglDeleteContext(wglHRC);
         ReleaseDC(wplat.hwnd_dialog, wglHDC);
         ReleaseDC(wplat.hwnd_dialog, hdc);

         if (wplat.multisamples)
            Con_Printf ("Multisample x %i Enabled (Requested %i, Received %i).\n", wplat.multisamples, ask_samples, wplat.multisamples);
         else Con_Warning ("Multisample: Requested but not available.\n");
      } else Con_Printf ("Note: Multisample not requested\n");

      // Post teardown
      DestroyWindow (wplat.hwnd_dialog);
      wplat.hwnd_dialog = NULL;
   }

Code: [Select]
BOOL WIN_SetupPixelFormat (HDC hDC)
{
    static PIXELFORMATDESCRIPTOR pfd = {
   sizeof(PIXELFORMATDESCRIPTOR),   // size of this pfd
   1,                  // version number
   PFD_DRAW_TO_WINDOW |   // support window
   PFD_SUPPORT_OPENGL |   // support OpenGL
   PFD_DOUBLEBUFFER,      // double buffered
   PFD_TYPE_RGBA,         // RGBA type
   24,                  // 24-bit color depth
   0, 0, 0, 0, 0, 0,      // color bits ignored
   0,                  // no alpha buffer
   0,                  // shift bit ignored
   0,                  // no accumulation buffer
   0, 0, 0, 0,          // accum bits ignored
   32,                  // 32-bit z-buffer
   8,                  // 8-bit stencil buffer
   0,                  // no auxiliary buffer
   PFD_MAIN_PLANE,         // main layer
   0,                  // reserved
   0, 0, 0               // layer masks ignored
    };
    int pixelformat;
   PIXELFORMATDESCRIPTOR  test; //johnfitz

#ifdef SUPPORTS_MULTISAMPLE // Baker change
   if (!wplat.multisamples)
   {
#endif // Baker change + #ifdef SUPPORTS_MULTISAMPLE // Baker change
      if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )
      {
         Sys_Error ("Video: ChoosePixelFormat failed");
         return FALSE;
      }
#ifdef SUPPORTS_MULTISAMPLE // Baker change
   } else pixelformat = wplat.forcePixelFormat; // Multisample overrride
#endif // Baker change + #ifdef SUPPORTS_MULTISAMPLE // Baker change

   DescribePixelFormat(hDC, pixelformat, sizeof(PIXELFORMATDESCRIPTOR), &test);

    if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE)
    {
        Sys_Error ("SetPixelFormat failed");
        return FALSE;
    }

#ifdef SUPPORTS_MULTISAMPLE // Baker change
   memcpy (&wplat.pfd, &pfd, sizeof(pfd) );
#endif // Baker change + #ifdef SUPPORTS_MULTISAMPLE // Baker change
    return TRUE;
}

Code: [Select]
#include "vid_wglext.h"      //WGL extensions

int   arbMultisampleSupported   = false;
int      arbMultisampleFormat   = 0;

// WGLisExtensionSupported: This Is A Form Of The Extension For WGL
int WGLisExtensionSupported(const char *extension)
{
   const size_t extlen = strlen(extension);
   const char *supported = NULL;
   const char* p;

   // Try To Use wglGetExtensionStringARB On Current DC, If Possible
   PROC wglGetExtString = wglGetProcAddress("wglGetExtensionsStringARB");

   if (wglGetExtString)
      supported = ((char*(__stdcall*)(HDC))wglGetExtString)(wglGetCurrentDC());

   // If That Failed, Try Standard Opengl Extensions String
   if (supported == NULL)
      supported = (char*)glGetString(GL_EXTENSIONS);

   // If That Failed Too, Must Be No Extensions Supported
   if (supported == NULL)
      return false;

   // Begin Examination At Start Of String, Increment By 1 On False Match
   for (p = supported; ; p++)
   {
      // Advance p Up To The Next Possible Match
      p = strstr(p, extension);

      if (p == NULL)
         return false;                                             // No Match

      // Make Sure That Match Is At The Start Of The String Or That
      // The Previous Char Is A Space, Or Else We Could Accidentally
      // Match "wglFunkywglExtension" With "wglExtension"

      // Also, Make Sure That The Following Character Is Space Or NULL
      // Or Else "wglExtensionTwo" Might Match "wglExtension"
      if ((p==supported || p[-1]==' ') && (p[extlen]=='\0' || p[extlen]==' '))
         return true;                                             // Match
   }
}

// InitMultisample: Used To Query The Multisample Frequencies
int WIN_InitMultisample (HINSTANCE hInstance,HWND hWnd,PIXELFORMATDESCRIPTOR pfd, int ask_samples, int* pixelForceFormat)

    // See If The String Exists In WGL!
   if (!WGLisExtensionSupported("WGL_ARB_multisample"))
   {
      arbMultisampleSupported=false;
      return false;
   }

   {     
      // Get Our Pixel Format
      PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");   
      if (!wglChoosePixelFormatARB)
      {
         arbMultisampleSupported=false;
         return false;
      }


      {
         // Get Our Current Device Context
         HDC hDC = GetDC(hWnd);

         int      pixelFormat;
         int      valid;
         UINT   numFormats;
         float   fAttributes[] = {0,0};

         // These Attributes Are The Bits We Want To Test For In Our Sample
         // Everything Is Pretty Standard, The Only One We Want To
         // Really Focus On Is The SAMPLE BUFFERS ARB And WGL SAMPLES
         // These Two Are Going To Do The Main Testing For Whether Or Not
         // We Support Multisampling On This Hardware.
         int iAttributes[] =
         {
            WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
            WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
            WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
            WGL_COLOR_BITS_ARB, 24 /*currentbpp? Nah */, // Baker: Mirror current bpp color depth?
            WGL_ALPHA_BITS_ARB,8,
            WGL_DEPTH_BITS_ARB,16,
            WGL_STENCIL_BITS_ARB,8, // Baker: Stencil bits
            WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
            WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
            WGL_SAMPLES_ARB, ask_samples /*multisample bits*/,
            0,0
         };

         
         while (ask_samples == 8 || ask_samples == 4 || ask_samples == 2)
         {
            iAttributes[19] = ask_samples;

            // First We Check To See If We Can Get A Pixel Format For 4 Samples
            valid = wglChoosePixelFormatARB(hDC,iAttributes,fAttributes,1,&pixelFormat,&numFormats);

            // If We Returned True, And Our Format Count Is Greater Than 1
            if (valid && numFormats >= 1)
            {           
               *pixelForceFormat = arbMultisampleFormat = pixelFormat;
               return (arbMultisampleSupported = ask_samples);
            }

            ask_samples >>= 1; // Divide by 2
         }
           
         // Return Fail
         return  (arbMultisampleSupported = 0);
      }
   }
}



Code: [Select]
      gl_state.wgl_nv_multisample_coverage = false;
      if (strstr(glw_state.wglExtsString, "WGL_NV_multisample_coverage")) {
     
      if(r_arbSamples->value < 2){
      Com_Printf(""S_COLOR_YELLOW"...ignoring WGL_NV_multisample_coverage\n");
      gl_state.wgl_nv_multisample_coverage = false;
      gl_state.wgl_nv_multisample_coverage_aviable = true;
      }else{
      Com_Printf("...using WGL_NV_multisample_coverage\n");
      gl_state.wgl_nv_multisample_coverage = true;
      gl_state.wgl_nv_multisample_coverage_aviable = true;
     
      if(r_arbSamples->value >=16){ // clamp regular msaa 16x value to csaa 16q
      Cvar_SetValue("r_arbSamples", 8);
      Cvar_SetValue("r_nvSamplesCoverange", 16);
      }

Code: [Select]
   iAttributes[0] = WGL_DOUBLE_BUFFER_ARB;
      iAttributes[1] = TRUE;
     
      if(gl_state.wgl_nv_multisample_coverage){
     
      iAttributes[2] = WGL_COLOR_SAMPLES_NV;
      iAttributes[3] = (int)r_arbSamples->value;
     
      }else{
     
      iAttributes[2] = WGL_COLOR_BITS_ARB;
      iAttributes[3] = 32;
      }

      iAttributes[4] = WGL_DEPTH_BITS_ARB;
      iAttributes[5] = 24;

      iAttributes[6] = WGL_ALPHA_BITS_ARB;
      iAttributes[7] = 8;

      iAttributes[8] = WGL_STENCIL_BITS_ARB;
      iAttributes[9] = 8;
     
      iAttributes[10] = arbMultisampleSupported ? WGL_SAMPLE_BUFFERS_ARB : 0;
      iAttributes[11] = arbMultisampleSupported ? TRUE : 0;
     
      if(gl_state.wgl_nv_multisample_coverage){
                     
      iAttributes[12] = arbMultisampleSupported ? WGL_COVERAGE_SAMPLES_NV : 0;
      iAttributes[13] = arbMultisampleSupported ? (int)r_nvSamplesCoverange->value : 0;
      }
      else
      {
      iAttributes[12] = arbMultisampleSupported ? WGL_SAMPLES_ARB : 0;
      iAttributes[13] = arbMultisampleSupported ? (int)r_arbSamples->value : 0;
      }
      iAttributes[14] = 0;
      iAttributes[15] = 0;

HaRmonY

  • VM-68
  • Posts: 211
Re: Feature: Multisampling/Antialiasing
« Reply #1 on: May 30, 2013, 06:12:29 AM »
What would be the changes?

TRION

  • 68 Carbine
  • Posts: 290
Re: Feature: Multisampling/Antialiasing
« Reply #2 on: May 30, 2013, 08:57:31 AM »
this code is encouraging me to start programming :) soo interesting!!

jitspoe

  • Administrator
  • Autococker
  • Posts: 18802
Re: Feature: Multisampling/Antialiasing
« Reply #3 on: May 30, 2013, 01:07:46 PM »
What would be the changes?
In short, it softens the "jagged edges" on polygons.

Example: http://solidlystated.com/software/divinity-2-anti-aliasing/

promarijan

  • VM-68
  • Posts: 182
Re: Feature: Multisampling/Antialiasing
« Reply #4 on: June 06, 2013, 01:43:04 PM »
Just put in your graphics control center (Nvidia/AMD) for the specific .exe the antialaising and anisitrope filtering if the game has a bad one or nothing like that and then enjoy!

jitspoe

  • Administrator
  • Autococker
  • Posts: 18802
Re: Feature: Multisampling/Antialiasing
« Reply #5 on: June 06, 2013, 02:24:19 PM »
Yeah, most graphics card drivers let you specify this on an application level, but it's still good to have the option available in-game for general support.