Posts

Showing posts with the label graphics

Lighting Theory: Radiometry and Photometry

Recent games have been heading towards Physically Based Rendering and this requires a solid understanding on lighting theory more than ever before. This time, I'm posting my note on Radiometry and Photometry . Radiometry Radiometry  is basically ideas + mathematical tools to describe light propagation + reflection. Radiative Transfer  is a study of transfer of radiant energy (which operates on geometric optics level - macroscopic properties of light suffice to describe how light interacts with objects much larger than light's wavelength). Four Radiometric Quantities : 1.  Flux (Radiant Flux/Power) - total amount of energy passing through a surface or region of space per unit time (J/s or Watt). Total emission from light sources is generally described in terms of flux. 2.  Irradiance (E) - area density of flux arriving at a surface (Watt/m2) Radiant Exitance (M) - area density of flux leaving a surface (Watt/m2) 3. Radiant Intensity (I) - flux dens...

D3D11 Compute Shader - Part 2

Image
To understand the concept of Compute Shader, let's start from basic. Compute Shader (CS) Threads A thread is basic CS processing element. 1. CPU kicks off CS thread groups. // Total number of thread groups = nX * nY * nZ pDevice->Dispatch( nX, nY, nZ ); 2. Each CS declares the number of threads on the "thread group". // Total number of threads per thread group = X * Y * Z [numthreads(X,Y,Z)] void cs_main(...) { ... } Example // CPU pDevice->Dispatch( 3, 2, 1 ); // CS [numthreads(4, 4, 1)] void cs_main(...) { ... } // # of thread groups = 3*2*1 = 6 // # of threads per group = 4*4*1 = 16 // # of total threads = 6 * 16 = 96 N.B: Picture taken from GDC09 Slide "Shader Model 5.0 and Compute Shader" CS Parameter Input void cs_main(uint3 groupID : SV_GroupID, uint3 groupThreadID : SV_GroupThreadID, uint3 dispatchThreadID : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) { ...

Computing Bent Cone

In rendering world, there are several article that discusses about bent cone. For example Bent Normals and Cones in Screen Space and also in GPU Pro 3: Screen-Space Bent Cones: A Practical Approach . In this post, I wanted to share how I compute bent cone (bent normal and max cone angle). The paper Bent Normals and Cones in Screen Space actually discusses how you compute bent normal and max cone angle (although it's a bit math-y). Here, I want to present how I compute it. Computing bent normal is quite easy, basically you just shoot rays from your sampling point (pixel/vertex) and average the unoccluded rays (and normalize it). For max angle, it turns out we can correlate it with AO: Let: A = Half Opening of Cone Angle AO = Ambient Occlusion Value AO = UnoccludedArea / TotalArea Where: TotalArea = Hemisphere Area = 2 * pi * r * r UnoccludedArea = Area covered by Solid Angle 2A = Solid Angle 2A * r * r = 2 * pi * (1 - cos...

Translucent Shadows Part I - Starcraft II

Shadows is an important visual cue for rendering and has been incorporated into recent games via shadow mapping technique. Most shadow mapping technique only concerns about opaque object shadows and there is not a lot of about translucent object shadows. Translucent Shadows in Starcraft II Review In Starcraft II - Effects & Techniques , Dominic Fillion mentions how they render translucent shadows in Starcraft II. Here's how the rendering works: Notes: * Requires second shadow map and color buffer. Let's name them as translucent shadow map and translucent shadow buffer. Shadow Maps Rendering * Opaque Shadow Map: render opaque objects to opaque shadow map * Translucent Shadow Map: render translucent objects to translucent shadow map (z-write on, z-test on with less equal, no alpha test, records depth of closest transparency) * Translucent Shadow Buffer: Clear to white, sort translucent objects front-to-back, use Opaque Shadow Map as z-buffer, no z-write off, z-...

D3D11 Compute Shader - Part 1

GPU has become a general purpose processor! or at least becoming more and more general. This is proved by the existence of GPGPU APIs such as DirectCompute, CUDA, OpenCL. It's time to start learning Compute Shader (CS), in this case, DirectCompute from D3D11. Past GPGPU Coders... Believe it or not GPGPU actually has existed before Compute Shaders arrived. However, you need to structure everything in terms of graphics, i.e. in order to launch GPGPU computation you have to render geometry and you basically use Pixel Shaders to do the computation. While this style of GPGPU coding can still work today, we can do much better! Compute Shaders allow us to use GPU just like we program a regular code. The first benefit is that you don't need to care about graphics pipeline and such, you just need to dispatch your Compute Shaders and that's it. In addition, Compute Shaders bypass graphics pipeline, i.e. primitive assembly, rasterization, etc2; so you have the potential to r...

Mapping Square Texture to Trapezoid / Quadrilateral

It turns out to be not a straightforward one. If you ever want to render trapezoid but mapped to square texture coordinate, i.e. (0,0) - (1,1), it won't turn out right. Turns out there's an easy way to fix this. Basically, instead of passing in float2 texture coordinates, you need to pass in the third coordinate to do projection on texture coordinates. The solution can be found here  http://stackoverflow.com/questions/15242507/perspective-correct-texturing-of-trapezoid-in-opengl-es-2-0 . Edit: It turns out, there's a more generic solution, i.e. quadrilateral interpolation: http://www.reedbeta.com/blog/2012/05/26/quadrilateral-interpolation-part-1/ Other references that might be useful: http://hacksoflife.blogspot.com/2009/11/perspective-correct-texturing-q.html http://www.xyzw.us/~cass/qcoord/ http://www.gamedev.net/topic/419296-skewedsheared-texture-mapping-in-opengl/

Reconstructing Position From Depth

Matt posted an excellent article about reconstructing position from depth. Check out his article here: http://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/ He has the following function to reconstruct View Space Position from Post Clip Space Position : // Function for converting depth to view-space position // in deferred pixel shader pass. vTexCoord is a texture // coordinate for a full-screen quad, such that x=0 is the // left of the screen, and y=0 is the top of the screen. float3 VSPositionFromDepth(float2 vTexCoord) { // Get the depth value for this pixel float z = tex2D(DepthSampler, vTexCoord); // Get x/w and y/w from the viewport position float x = vTexCoord.x * 2 - 1; float y = (1 - vTexCoord.y) * 2 - 1; float4 vProjectedPos = float4(x, y, z, 1.0f); // Transform by the inverse projection matrix float4 vPositionVS = mul(vProjectedPos, g_matInvProjection); // Divide by w to get the view-space position ...

Avoiding Branch in Shader

Depending on which platform and target hardware, it can be a good idea to eliminate branches in shader. Here's two techniques with samples. Lerp Lerp, a.k.a. linear interpolation, is a useful function to select between two things. If you have two vectors v1, v2 and you want to select one of them based on some condition, lerp can be used. Make sure that the result of the condition (conditionMask)  is always 0 or 1.  You can then do this: result = lerp(v1, v2, conditionMask); If your condition is 0, it will return v1. If your condition is 1, it will return v2. Min/Max Min and max is very useful in some cases. For example, let say you want to have one shader to switch between lit and not-lit. Typically, we will multiply the lighting value with color. For instance: light = CalcLighting(); color *= light; So, the condition would be, if there's no lighting return 1; otherwise return the lighting value. We can easily do this with Lerp. light = lerp(1, CalcLighting(), isLi...