Game Development Community

CryEngine 3 Tech Demo

by Brandon Pollet · 08/12/2009 (3:34 pm) · 9 comments

On the CryEngine 3 specifications page there is a description of the new 'Real-Time Global Illumination System' used in the engine.

CryENGINE® 3 features a novel real-time dynamic global illumination solution, fully optimised for current and next generation platforms. For the first time – without pre-computation or geometric limits – you can experience light-bounces, colour bleeding and specular effects in a real-time game engine – unified for all static and dynamic objects.

In the video below you can see the awesome use of color bleeding and light bouncing in action. I first noticed the effect in the columns as you can see the red and blue hues show up on the white stone. It's an effect that really helps to give the scene an authenticity that most 3D engines lack.

Check out the video here: quicksavegames.com/blog/show/77?t=CryEngine+3+Tech+Demo

#1
08/12/2009 (4:42 pm)
This had to be the most disappointing demo/paper out of SIGGRAPH. I think they must have gotten Kool-Aid in bulk. Props for an implementation that works; but any GI paper which glosses over light-probes, and assumes that they are cube-map based, is a poor solution.

The real stuff out of SIGGRAPH is over here:
graphics.cs.uiuc.edu/~kircher/publications.html

The DSF work is, in my opinion, the single largest contribution to the current rendering paradigm since linear depth. I am busting at the seams with things I want to try using this, from mixed-resolution rendering, to upscaling, to more translucency work.
#2
08/12/2009 (11:24 pm)
It is interesting but I think that the goals are not the same. The one you mention has nothing to do with radiosity or GI. at least not in their presentation. The transparency thing without alpha testing does look nice though. GI and Radiosity seem to be the sole goal of the Crytek presentation.

There was another Video on the CryEngine 3 feature that better illustrates the Radiosity but I cannot seam to find it now. it shows it affecting animated characters and what not.

the TRansparency issue is a big one though prolly one of the single biggest pains still to this day.
#3
08/13/2009 (12:41 am)
CryTek's


SSGI from Arkano22



SSGI of some sort



Arkano22 converted from GLSL to HLSL
#define GI_NUM_SAMPLES 8

//-----------------------------------------------------------------------------
// Structures                                                                  
//-----------------------------------------------------------------------------
struct PS_INPUT
{
   float4 Position : POSITION0;
   float4 Texcoord : TEXCOORD0;
};

struct PS_OUTPUT
{
   float4 Color : COLOR0;
};

//-----------------------------------------------------------------------------
// Functions                                                                  
//-----------------------------------------------------------------------------

//noise producing function to eliminate banding (got it from someone else´s shader):
float GIrand(float2 co)
{
 return 0.5+(fract(sin(dot(co.xy ,float2(12.9898,78.233))) * 43758.5453))*0.5;
};

//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
PS_OUTPUT main(PS_INPUT Input,
         uniform sampler2D GIsom : register(S0),
         uniform sampler2D GInormal : register(S2),
         uniform sampler2D GIcolor : register(S3))
{
 PS_OUTPUT Output;
   
 //calculate sampling rates:
 float ratex = (1.0/1024.0);
 float ratey = (1.0/768.0);

 //initialize occlusion sum and gi color:
 float sum = 0.0;
 float3 fcolor = float3(0,0,0);

 //far and near clip planes:
 float zFar = 80.0;
 float zNear = 0.5;

 //get depth at current pixel:
 float prof = texture2D(GIsom, Input.Texcoord.xy).x;

 //scale sample number with depth:
 int samples = round(NUM_SAMPLES/(0.5+prof));
 prof = zFar * zNear / (prof * (zFar - zNear) - zFar);  //linearize z sample

 //obtain normal and color at current pixel:
 float3 norm = normalize(float3(texture2D(GInormal,Input.Texcoord.xy).xyz)*2.0-float3(1.0));
 float3 dcolor1 = texture2D(GIcolor, Input.Texcoord.xy);

 int hf = samples/2;

 //calculate kernel steps:
 float incx = ratex*30;//gi radius
 float incy = ratey*30;

 float incx2 = ratex*8;//ao radius
 float incy2 = ratey*8;

 //do the actual calculations:
 for(int i=-hf; i < hf; i++)
 {
  for(int j=-hf; j < hf; j++)
  {
   if (i != 0 || j!= 0) 
   {
    float2 coords = float2(i*incx,j*incy)/prof;
    float2 coords2 = float2(i*incx2,j*incy2)/prof;

    float prof2 = texture2D(GIsom,Input.Texcoord.xy+coords*GIrand(Input.Texcoord)).x;
    prof2 = zFar * zNear / (prof2 * (zFar - zNear) - zFar);  //linearize z sample

    float prof2g = texture2D(GIsom,Input.Texcoord.xy+coords2*GIrand(Input.Texcoord)).x;
    prof2g = zFar * zNear / (prof2g * (zFar - zNear) - zFar);  //linearize z sample

    float3 norm2g = normalize(float3(texture2D(GInormal,Input.Texcoord.xy+coords2*GIrand(Input.Texcoord)).xyz)*2.0-float3(1.0)); 

    float3 dcolor2 = texture2D(GIcolor, Input.Texcoord.xy+coords*GIrand(Input.Texcoord));

    //OCCLUSION:

    //calculate approximate pixel distance:
    float3 dist2 = float3(coords2,prof-prof2g);

    //calculate normal and sampling direction coherence:
    float coherence2 = dot(normalize(-coords2),normalize(float2(norm2g.xy)));

    //if there is coherence, calculate occlusion:
    if (coherence2 > 0)
    {
     float pformfactor2 = 0.5*((1.0-dot(norm,norm2g)))/(3.1416*pow(abs(length(dist2*2)),2.0)+0.5);//el 4: depthscale
     sum += clamp(pformfactor2*0.2,0.0,1.0);//ao intensity; 
    }

    //COLOR BLEEDING:
    if (length(dcolor2)>0.3)
    {
     //color threshold
     float3 norm2 = normalize(float3(texture2D(GInormal,Input.Texcoord.xy+coords*GIrand(Input.Texcoord)).xyz)*2.0-float3(1.0)); 
          
     //calculate approximate pixel distance:
     float3 dist = float3(coords,abs(prof-prof2));

     //calculate normal and sampling direction coherence:
     float coherence = dot(normalize(-coords),normalize(float2(norm2.xy)));

     //if there is coherence, calculate bleeding:
     if (coherence > 0)
     {
      float pformfactor = ((1.0-dot(norm,norm2)))/(3.1416*pow(abs(length(dist*2)),2.0)+0.5);   //el 4: depthscale
      fcolor += dcolor2*(clamp(pformfactor,0.0,1.0));
     }
    }
   }
  }
 }

 float3 bleeding = (fcolor/samples)*0.5;
 float occlusion = 1.0-(sum/samples);
 //gl_FragColor = float4(float3(dcolor1*occlusion+bleeding*0.5),1.0);
 
 Output.Color = float4(1,1,1,1);
 Output.Color = float4(float3(dcolor1*occlusion+bleeding*0.5),1.0);
 
 return Output;
};
#4
08/13/2009 (2:21 am)
Oh actually I didn't mean to compare the techniques in that respect at all.

The GI solution has been published (well I think it is the GI solution with the best scalability/best implementation); it's called Imperfect Shadow Maps

Here is a video:

OmegaDog: SSGI is chasing something which can't exist. I am personally sick to death of SSAO and SSGI. It's a cool hack, but a horrible waste of fillrate, for what becomes an untweekable parameter in your scene. There are the parameters of the effect, but the problem is that you frequently need/want to make adjustments on a per/object or per/room basis. Sometimes it works, and that is cool, but it really is not a good solution to the problem. Screen-Space does not contain the information needed to compute either ambient occlusion, or global illumination. ISM's solve that problem.

We just need to wait for Larabee ;)
#5
08/13/2009 (2:27 am)
WOW sweet! Larabee???
#6
08/13/2009 (2:46 am)
Well that demo is done on a GeForce I am pretty sure. The problem is that it is very slow. The good news, is that it is a very scaleable method, and I think it will work well on Larabee. That remains to be seen, but I think that what I'd call "probe based methods" for GI are going to be the winners, and not the computational models, like Crytek's and SSGI. That is just my opinion, though. We will see.
#8
08/13/2009 (3:59 am)
Right, and while I haven't looked at their stuff, I think they are on the right track (well a lot of people are).

The Crytek solution is cascaded, which means it's camera dependent, and will need to be updated every frame. A probe-based solution can be selectivly updated based on a priority system. The 'probe-based' solutions (ISM, Lightsprint, various VPL type things, etc) can be scaled in both number, and resolution. Probe based can be pre-computed easily, I am not sure about that other technique. Largely I think that a good portion if the Crytek method has been previously covered by Forsyth and the Irradiance Volumes DX demo.

The biggest kind of "crazy bit" of ISM is the point-based scene representation. This is an important bit, but I am not entirely convinced it is ready for prime-time. It's cool, don't get me wrong, and I actually want to do a push/pull variation for my single-pass dual-paraboloid method. I just think that it's an awefully big demand to have a point-cloud based scene representation. Until we can do everything in voxels or something, geometry is needed. I think that using low-res models, and doing some clever things with instancing may be the solution. Right now, people seem to be taking the approach of, "render each 'probe' completely and then move on to the next one." This is kind of silly, and if I had a good month or so to spend researching...man I'd have something good to talk about at GDC. Unfortunately there are many other priorities.
#9
08/19/2009 (6:40 am)
There are enough GPU cores in nvidia 290 and radeon 4870 series to perform real-time ray tracing, seems like CryEngine 3 is exploring it - did I get it right?
I did see a small demo of real-time ray tracing on geforce gtx 275, it was giving about 10fps on a fairly complex scene with reflections (as we know the triangle count does not affect ray tracing much), without that many reflections it could go to 30fps mark, I believe. I cannot find a link to that video anymore...